├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── ROADMAP.md ├── assets └── kaiwu_match.jpg ├── benchmark ├── aircraft │ ├── asset │ │ ├── airship.png │ │ └── drone.png │ ├── check_ac_env.py │ └── utils │ │ ├── __init__.py │ │ ├── ac_env.py │ │ └── ac_wrapper.py ├── sumo_envs │ ├── J1 │ │ ├── add │ │ │ ├── e2.add.xml │ │ │ └── tls.add.xml │ │ └── env │ │ │ ├── J1.net.xml │ │ │ ├── J1.rou.xml │ │ │ └── J1.sumocfg │ ├── OSM │ │ ├── add │ │ │ ├── e2.add.xml │ │ │ └── tls.add.xml │ │ ├── env │ │ │ ├── osm.net.xml │ │ │ ├── osm.png │ │ │ ├── osm.rou.xml │ │ │ ├── osm.sumocfg │ │ │ └── viewsettings.xml │ │ └── generate_routes_osm.py │ ├── multi_junctions_tsc │ │ ├── add │ │ │ ├── e1.add.xml │ │ │ ├── e1_internal.add.xml │ │ │ ├── e2.add.xml │ │ │ ├── e3.add.xml │ │ │ └── tls.add.xml │ │ ├── env │ │ │ ├── three_junctions.net.xml │ │ │ ├── three_junctions.rou.xml │ │ │ └── three_junctions.sumocfg │ │ └── generate_routes.py │ ├── veh_bottleneck │ │ ├── veh.net.xml │ │ ├── veh.sumocfg │ │ └── veh_threeagents.rou.xml │ └── veh_rlhf │ │ ├── generate_routes_veh.py │ │ ├── veh_rlhf.net.xml │ │ ├── veh_rlhf.rou.xml │ │ └── veh_rlhf.sumocfg ├── traffic_light │ ├── README.md │ ├── assets │ │ ├── multi_agents_reward.png │ │ ├── multi_agents_rl.gif │ │ ├── single_agent_reward.png │ │ └── single_agent_rl.gif │ ├── multi_agents │ │ ├── check_pz_env.py │ │ ├── check_rl_env.py │ │ ├── check_rl_parallel_env.py │ │ ├── env_utils │ │ │ ├── make_tsc_env.py │ │ │ ├── pz_env.py │ │ │ ├── tsc_env.py │ │ │ └── tsc_wrapper.py │ │ ├── eval_mappo.py │ │ ├── log │ │ │ ├── 0.monitor.csv │ │ │ ├── 1.monitor.csv │ │ │ ├── 2.monitor.csv │ │ │ ├── 3.monitor.csv │ │ │ ├── 4.monitor.csv │ │ │ ├── 5.monitor.csv │ │ │ ├── eval.monitor.csv │ │ │ ├── rl_env.monitor.csv │ │ │ └── tsc_pz_env.monitor.csv │ │ ├── mappo_tensorboard │ │ │ └── events.out.tfevents.1698766231.WMNPower.77672.0 │ │ ├── plot_rewards.py │ │ ├── reward.png │ │ ├── train_mappo.py │ │ └── train_utils │ │ │ ├── make_log.py │ │ │ └── make_modules.py │ └── single_agent │ │ ├── check_tsc_env.py │ │ ├── eval_rl_agent.py │ │ ├── log │ │ ├── 0.monitor.csv │ │ ├── 1.monitor.csv │ │ ├── 2.monitor.csv │ │ ├── 3.monitor.csv │ │ ├── 4.monitor.csv │ │ └── 5.monitor.csv │ │ ├── models │ │ ├── last_rl_model.zip │ │ └── last_vec_normalize.pkl │ │ ├── plot_rewards.py │ │ ├── ruled_method.py │ │ ├── sb3_ppo.py │ │ ├── tensorboard │ │ └── J1_tensorboard.tfevents │ │ └── utils │ │ ├── __init__.py │ │ ├── custom_models.py │ │ ├── make_tsc_env.py │ │ ├── sb3_utils.py │ │ ├── tsc_env.py │ │ └── tsc_wrapper.py ├── vehicle_bottleneck │ ├── __init__.py │ ├── check_pz_env.py │ ├── check_rl_parallel_env.py │ ├── check_vehicle_env.py │ ├── env_utils │ │ ├── __Init__.py │ │ ├── make_veh_env.py │ │ ├── pz_veh_env.py │ │ ├── veh_env.py │ │ ├── veh_wrapper.py │ │ └── wrapper_utils.py │ ├── eval_mappo.py │ ├── plot_rewards.py │ ├── single_agent │ │ ├── check_ego_env.py │ │ ├── eval_rl_agent.py │ │ ├── plot_rewards.py │ │ ├── sb3_ppo.py │ │ └── utils │ │ │ ├── __Init__.py │ │ │ ├── custom_models.py │ │ │ ├── make_veh_env.py │ │ │ ├── sb3_utils.py │ │ │ ├── veh_env.py │ │ │ ├── veh_wrapper.py │ │ │ └── wrapper_utils.py │ ├── train_mappo.py │ └── train_utils │ │ ├── make_log.py │ │ └── make_modules.py └── vehicle_rlhf │ ├── check_vehicle_env.py │ └── utils │ ├── veh_env.py │ └── veh_wrapper.py ├── docs ├── .readthedocs.yaml ├── Makefile ├── make.bat ├── requirements.txt └── source │ ├── _static │ ├── object │ │ ├── aircraft_action.gif │ │ ├── single_junction.png │ │ ├── traffic_light_example.gif │ │ └── vehicle_example.gif │ ├── stepbystep_tutorial │ │ └── create_scenario │ │ │ ├── background_view_setting.png │ │ │ ├── create_scenario_flow.gif │ │ │ ├── osm_export.png │ │ │ ├── sumo_net.png │ │ │ └── sumonet_background.png │ ├── sumo_tools │ │ ├── detector_add.png │ │ ├── e2_detectors.png │ │ └── flow_interpolation.png │ ├── tshub3d_sensors │ │ ├── aircraft │ │ │ ├── follow_vehicle.gif │ │ │ ├── horizontal.gif │ │ │ └── vertical.gif │ │ ├── junction │ │ │ ├── junction_back.gif │ │ │ ├── junction_back_example.png │ │ │ ├── junction_front.gif │ │ │ └── junction_front_example.png │ │ ├── traffic_scenario │ │ │ ├── sumo.gif │ │ │ └── tshub3d.gif │ │ ├── vehicle │ │ │ ├── vehicle_ego0_all.gif │ │ │ ├── vehicle_ego0_vehicle.gif │ │ │ ├── vehicle_ego1_all.gif │ │ │ ├── vehicle_ego1_vehicle.gif │ │ │ ├── vehicle_ego2_all.gif │ │ │ ├── vehicle_ego2_vehicle.gif │ │ │ └── vehicle_sensor_example.png │ │ └── vehicle_types │ │ │ ├── emergency.png │ │ │ ├── fire_engine.png │ │ │ ├── police.png │ │ │ ├── suv_blue.png │ │ │ ├── suv_grey.png │ │ │ ├── suv_orange.png │ │ │ ├── taxi.png │ │ │ ├── vehicle_blue.png │ │ │ ├── vehicle_pink.png │ │ │ └── vehicle_white.png │ └── v2x │ │ └── packet_loss.png │ ├── conf.py │ ├── index.rst │ └── locales │ ├── en │ ├── index.rst │ ├── installation │ │ └── index.rst │ ├── introduction │ │ └── index.rst │ └── tshub3d_sensors │ │ ├── aircraft.rst │ │ ├── index.rst │ │ ├── junction.rst │ │ ├── traffic_scenario.rst │ │ ├── vehicle.rst │ │ └── vehicle_types.rst │ └── zh_CN │ ├── index.rst │ ├── installation │ └── index.rst │ ├── introduction │ └── index.rst │ ├── object │ ├── aircraft.rst │ ├── index.rst │ ├── traffic_light.rst │ └── vehicle.rst │ ├── stepbystep_tutorial │ ├── create_scenario.rst │ └── index.rst │ ├── sumo_tools │ ├── generate_detectors.rst │ ├── generate_routes.rst │ ├── index.rst │ └── tls_addition.rst │ ├── tshub3d_sensors │ ├── aircraft.rst │ ├── index.rst │ ├── junction.rst │ ├── traffic_scenario.rst │ ├── vehicle.rst │ └── vehicle_types.rst │ └── v2x │ ├── index.rst │ ├── outage_probability.rst │ └── v2x.rst ├── examples ├── aircraft │ ├── aircraft_actions │ │ ├── aircraft_combined.py │ │ ├── aircraft_horizontal.py │ │ ├── aircraft_stationary.py │ │ └── aircraft_vectical.py │ ├── aircraft_custom_update_cover_radius.py │ └── get_aircraft_state.py ├── map │ ├── get_grid_info.py │ ├── get_net_info.py │ ├── get_poly_info.py │ ├── plot_net.py │ └── polt_poly_shape.py ├── person │ └── get_person_state.py ├── sumo_env │ ├── ego_crash │ │ ├── ego_crash_car_following │ │ │ ├── env.sumocfg │ │ │ ├── lane.net.xml │ │ │ └── lane.rou.xml │ │ ├── ego_crash_intersection │ │ │ ├── add │ │ │ │ ├── tls_programs.add.xml │ │ │ │ ├── tls_state.add.xml │ │ │ │ ├── tls_switch_states.add.xml │ │ │ │ └── tls_switches.add.xml │ │ │ ├── env.sumocfg │ │ │ ├── inter.net.xml │ │ │ ├── inter.rou.xml │ │ │ └── inter_tsc.net.xml │ │ └── ego_crash_lane_change │ │ │ ├── bottleneck.rou.xml │ │ │ ├── scenario.sumocfg │ │ │ └── veh.net.xml │ ├── osm_berlin │ │ ├── add │ │ │ ├── e2.add.xml │ │ │ └── tls.add.xml │ │ ├── berlin.osm │ │ ├── env │ │ │ ├── background.png │ │ │ ├── berlin.net.xml │ │ │ ├── berlin.netgcfg │ │ │ ├── berlin.poly.xml │ │ │ ├── berlin.polygcfg │ │ │ ├── berlin.rou.xml │ │ │ ├── berlin.sumocfg │ │ │ └── viewsettings.xml │ │ └── script │ │ │ ├── generate_routes.py │ │ │ ├── generate_tls_additions.py │ │ │ └── generate_tls_detectors.py │ ├── pedestrian_cross │ │ ├── add │ │ │ └── tls.add.xml │ │ ├── detectors │ │ │ ├── e1.add.xml │ │ │ ├── e1_internal.add.xml │ │ │ ├── e2.add.xml │ │ │ └── e3.add.xml │ │ └── env │ │ │ ├── pedestrian.rou.xml │ │ │ ├── pedestrian_cross.net.xml │ │ │ ├── pedestrian_cross.sumocfg │ │ │ └── vehicle.rou.xml │ ├── single_junction │ │ ├── add │ │ │ └── tls.add.xml │ │ ├── detectors │ │ │ ├── e1_internal.add.xml │ │ │ └── e2.add.xml │ │ ├── env │ │ │ ├── single_junction.net.xml │ │ │ ├── single_junction.sumocfg │ │ │ └── straight.rou.xml │ │ └── generate_routes.py │ └── three_junctions │ │ ├── add │ │ └── tls.add.xml │ │ ├── detectors │ │ ├── e1.add.xml │ │ ├── e1_internal.add.xml │ │ ├── e2.add.xml │ │ └── e3.add.xml │ │ └── env │ │ ├── 3junctions.net.xml │ │ ├── 3junctions.rou.xml │ │ └── 3junctions.sumocfg ├── sumo_tools │ ├── additional_file │ │ └── tls_additions.py │ ├── analysis_output │ │ ├── add │ │ │ └── tls_program.out.xml │ │ ├── analysis_route.py │ │ ├── analysis_tls_program.py │ │ ├── analysis_tls_program_visualization.py │ │ └── analysis_tripinfo.py │ ├── generate_pedestrian_route.py │ ├── generate_route │ │ ├── trip.py │ │ └── turn_def.py │ ├── generate_routes.py │ ├── generate_routes_fromOD.py │ ├── generate_tls_detectors.py │ ├── interpolation │ │ ├── flow.py │ │ └── turn_prob.py │ ├── osm_build.py │ ├── osm_filter.py │ └── sumo_infos │ │ ├── get_edge_info.py │ │ └── get_tls_connections.py ├── traffic_light │ ├── get_tls_state.py │ └── traffic_light_action │ │ ├── tls_adjustCycleDuration.py │ │ ├── tls_choosenextphase.py │ │ ├── tls_choosenextphase_syn.py │ │ ├── tls_nextornot.py │ │ └── tls_setPhaseDuration.py ├── tshub_dataset │ └── osm2net.py ├── tshub_env │ ├── tshub_env_all_objects.py │ ├── tshub_env_map.py │ ├── tshub_env_output.py │ ├── tshub_env_person.py │ └── tshub_env_vehicle_crash.py ├── tshub_env3d │ ├── map_model_merge │ │ ├── model │ │ │ ├── ground.glb │ │ │ ├── lane_lines.glb │ │ │ ├── map.glb │ │ │ └── road_lines.glb │ │ ├── sumo │ │ │ ├── merge.net.xml │ │ │ ├── merge.rou.xml │ │ │ └── merge.sumocfg │ │ ├── sumonet_to_3d.py │ │ └── vehicle_view.py │ ├── multi_junctions │ │ ├── 3d_assets │ │ │ ├── ground.glb │ │ │ ├── lane_lines.glb │ │ │ ├── map.glb │ │ │ └── road_lines.glb │ │ ├── a_sumonet_to_3d.py │ │ ├── b_multi_junctions_aircraft.py │ │ ├── c_multi_junctions_tls.py │ │ └── sumo_net │ │ │ ├── generate_routes.py │ │ │ ├── multi_junctions.net.xml │ │ │ ├── multi_junctions.rou.xml │ │ │ └── multi_junctions.sumocfg │ ├── save_env3d_to_gif.py │ └── single_junction │ │ ├── 3d_assets │ │ ├── ground.glb │ │ ├── lane_lines.glb │ │ ├── map.glb │ │ └── road_lines.glb │ │ ├── a_sumonet_to_3d.py │ │ ├── b_aircraft_view.py │ │ ├── c_tls_view.py │ │ ├── d_vehicle_view.py │ │ ├── e_tls_view_save_image.py │ │ └── sumo_net │ │ ├── generate_routes.py │ │ ├── single_junction.net.xml │ │ ├── single_junction.rou.xml │ │ └── single_junction.sumocfg ├── tshub_env_render │ ├── README.md │ ├── assets │ │ ├── rgb_global.gif │ │ ├── rgb_node.gif │ │ ├── rgb_vehicle.gif │ │ ├── sumogui_global.gif │ │ ├── sumogui_node.gif │ │ └── sumogui_vehicle.gif │ ├── rgb_render │ │ ├── render_global.py │ │ ├── render_node.py │ │ └── render_vehicle.py │ └── sumo_gui_render │ │ ├── render_global.py │ │ ├── render_node.py │ │ └── render_vehicle.py ├── utils │ ├── nested_dict_example.py │ └── parse_trip_info │ │ ├── analysis_trip_info.py │ │ ├── output.csv │ │ ├── simulate_with_trioinfo.py │ │ └── single_junction.tripinfo.xml ├── v2x │ ├── v2x │ │ ├── i2v_channel.py │ │ ├── v2i_channel.py │ │ └── v2v_channel.py │ ├── v2x_tshub_cosim │ │ └── single_junction_v2x.py │ └── v2x_utils │ │ └── snr_to_packetloss.py └── vehicles │ ├── ego_vehicles │ ├── vehicle_ego.py │ ├── vehicle_laneChange_crash.py │ └── vehicle_speed_crash.py │ ├── get_vehicle_state.py │ └── vehicle_action │ ├── vehicle_lane.py │ ├── vehicle_lane_with_continuous_speed.py │ └── vehicle_speed.py ├── requirements.txt ├── setup.py ├── test └── test_tshub_version.py └── tshub ├── __init__.py ├── aircraft ├── __init__.py ├── aircraft.png ├── aircraft.py ├── aircraft_action_type.py ├── aircraft_builder.py └── aircraft_type │ ├── __init__.py │ ├── base_aircraft_action.py │ ├── combined_movement.py │ ├── horizontal_movement.py │ ├── stationary.py │ └── vertical_movement.py ├── features └── __init__.py ├── map ├── __init__.py ├── grid.py ├── map_builder.py └── polygon.py ├── person ├── __init__.py ├── person.py └── person_builder.py ├── sumo_tools ├── __init__.py ├── additional_files │ ├── __init__.py │ └── traffic_light_additions.py ├── analysis_output │ ├── __init__.py │ ├── route_analysis.py │ ├── tls_program_analysis.py │ ├── tls_program_visualization.py │ └── tripinfo_analysis.py ├── detectors │ ├── __init__.py │ ├── base_detectors.py │ ├── e1_detectors.py │ ├── e1_internal_detectors.py │ ├── e2_detectors.py │ └── e3_detectors.py ├── generate_detectors.py ├── generate_route │ ├── __init__.py │ ├── generate_odTrip.py │ ├── generate_person.py │ ├── generate_trip.py │ └── generate_turn_def.py ├── generate_routes.py ├── generate_routes_fromOD.py ├── interpolation │ ├── __init__.py │ ├── repeat_values.py │ ├── values_interpolation.py │ └── visualize_interpolations.py ├── osm_build.py ├── osm_build_type │ ├── __init__.py │ ├── net.typ.xml │ └── poly.typ.xml ├── osm_filter.py └── sumo_infos │ ├── __init__.py │ ├── edge_info.py │ ├── tls_connections.py │ ├── traffic_light_ids.py │ └── turndef │ ├── __init__.py │ ├── connections.py │ └── turndefinitions.py ├── traffic_light ├── __init__.py ├── tls_type │ ├── __init__.py │ ├── adjust_cycle_duration.py │ ├── base_tls.py │ ├── choose_next_phase.py │ ├── choose_next_phase_syn.py │ ├── next_or_not.py │ └── set_phase_duration.py ├── traffic_light.py ├── traffic_light_action_type.py ├── traffic_light_builder.py └── traffic_light_feature_convert.py ├── tshub_env ├── __init__.py ├── base_builder.py ├── base_sumo_env.py └── tshub_env.py ├── tshub_env3d ├── __init__.py ├── _assets_3d │ ├── map_road_lines │ │ ├── dashed_line_shader.frag │ │ └── dashed_line_shader.vert │ ├── shader │ │ ├── unlit_shader.frag │ │ └── unlit_shader.vert │ ├── skybox │ │ ├── skybox.bam │ │ ├── skybox.frag.glsl │ │ ├── skybox.jpg │ │ └── skybox.vert.glsl │ ├── terrain │ │ ├── terrain.frag.glsl │ │ └── terrain.vert.glsl │ └── vehicles │ │ ├── README.md │ │ ├── _assets │ │ ├── emergency.png │ │ ├── fire_engine.png │ │ ├── police.png │ │ ├── suv_blue.png │ │ ├── suv_grey.png │ │ ├── suv_orange.png │ │ ├── taxi.png │ │ ├── vehicle_blue.png │ │ ├── vehicle_pink.png │ │ └── vehicle_white.png │ │ └── blender2bam.txt ├── base_env3d.py ├── show_sensor_images.py ├── tshub_env3d.py ├── vis3d_output_tools │ ├── __init__.py │ └── merge_gif.py ├── vis3d_renderer │ ├── __init__.py │ ├── _showbase_instance.py │ ├── base_render.py │ ├── rendering_components │ │ ├── __init__.py │ │ ├── scene_loader.py │ │ └── scene_sync.py │ ├── sensors │ │ ├── __init__.py │ │ ├── base_sensors │ │ │ ├── __init__.py │ │ │ ├── base_camera_sensor.py │ │ │ └── base_sensor.py │ │ ├── cameras │ │ │ ├── __init__.py │ │ │ ├── build_offscreen_camera.py │ │ │ └── offscreen_camera │ │ │ │ ├── __init__.py │ │ │ │ ├── aircraft_camera.py │ │ │ │ ├── back_camera.py │ │ │ │ ├── base_offscreen_camera │ │ │ │ ├── __init__.py │ │ │ │ ├── base_off_camera.py │ │ │ │ └── base_off_camera_mixin.py │ │ │ │ ├── bev_camera.py │ │ │ │ ├── front_camera.py │ │ │ │ ├── junction_camera.py │ │ │ │ └── offscreen_camera_type.py │ │ └── rgb_sensor.py │ ├── traffic_elements │ │ ├── __init__.py │ │ ├── aircraft.py │ │ ├── base_element.py │ │ ├── traffic_signals.py │ │ └── vehicle.py │ └── tshub_render.py ├── vis3d_sumonet_convert │ ├── __init__.py │ ├── element_to_glb │ │ ├── __init__.py │ │ ├── ground_glb.py │ │ ├── lane_glb.py │ │ ├── map_glb.py │ │ └── road_glb.py │ ├── map_elements │ │ ├── __init__.py │ │ ├── base_road_map.py │ │ ├── feature.py │ │ ├── lane.py │ │ ├── road.py │ │ └── surface.py │ ├── sumonet_convert_utils │ │ ├── __init__.py │ │ ├── geometry.py │ │ └── glb_data.py │ └── sumonet_to_tshub3d.py └── vis3d_utils │ ├── __init__.py │ ├── colors.py │ ├── coordinates.py │ ├── core_math.py │ └── masks.py ├── utils ├── __init__.py ├── check_folder.py ├── format_dict.py ├── get_abs_path.py ├── init_log.py ├── nested_dict_conversion.py ├── normalization_dict.py ├── parse_trip_info.py ├── plot_reward_curves.py └── plt_to_array.py ├── v2x ├── README.md ├── __init__.py ├── v2i_channel.py ├── v2v_channel.py ├── v2x_channel.py └── v2x_utils │ ├── __init__.py │ └── snr_to_packetloss.py ├── vehicle ├── __init__.py ├── vehicle.py ├── vehicle_action_type.py ├── vehicle_builder.py └── vehicle_type │ ├── __init__.py │ ├── base_vehicle_action.py │ ├── lane.py │ ├── lane_with_continuous_speed.py │ └── speed.py └── visualization ├── __init__.py ├── filter_objects.py ├── vis_map_feature.py ├── vis_vehicles.py └── visualize_map.py /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include tshub/aircraft/aircraft.png 2 | include tshub/sumo_tools/osm_build_type/net.typ.xml 3 | include tshub/sumo_tools/osm_build_type/poly.typ.xml 4 | recursive-include tshub/tshub_env3d/_assets_3d/ * -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 7 | # TransSimHub 8 | 9 | TransSimHub is a lightweight Python library for simulating and controlling transportation systems. 10 | 11 | Get started at 12 | [English Docs](https://transsimhub.readthedocs.io/en/latest/) | 13 | [中文文档](https://transsimhub.readthedocs.io/en/latest/locales/zh_CN/index.html) 14 | 15 | ## Test 16 | 17 | 1. **Run the Tests:** You can use Python's unittest discovery mode to automatically find and run tests. From the root directory of your project, run: 18 | 19 | ```shell 20 | python -m unittest discover -s test 21 | ``` 22 | 23 | The `-s test` option tells unittest to start discovery in the `test` directory. Python will automatically find files named like `test*.py` and execute the test cases defined within them. 24 | 25 | 2. **Review the Test Results:** 26 | - An `OK` output indicates all tests passed, confirming the `tshub` package is installed correctly and its version is greater than 1. 27 | - A `FAIL` or `ERROR` output indicates some tests did not pass. Review the output details to understand what went wrong. 28 | -------------------------------------------------------------------------------- /assets/kaiwu_match.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/assets/kaiwu_match.jpg -------------------------------------------------------------------------------- /benchmark/aircraft/asset/airship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/aircraft/asset/airship.png -------------------------------------------------------------------------------- /benchmark/aircraft/asset/drone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/aircraft/asset/drone.png -------------------------------------------------------------------------------- /benchmark/aircraft/utils/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-14 13:48:06 4 | @Description: 5 | @LastEditTime: 2023-09-14 13:48:08 6 | ''' 7 | -------------------------------------------------------------------------------- /benchmark/aircraft/utils/ac_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-14 13:48:19 4 | @Description: Aircraft Environment 5 | @LastEditTime: 2023-09-14 16:02:21 6 | ''' 7 | import gymnasium as gym 8 | 9 | from typing import Dict, Any 10 | from tshub.tshub_env.tshub_env import TshubEnvironment 11 | 12 | class ACEnvironment(gym.Env): 13 | def __init__(self, sumo_cfg:str, num_seconds:int, aircraft_inits:Dict[str, Any], use_gui:bool=False) -> None: 14 | super().__init__() 15 | 16 | self.tsc_env = TshubEnvironment( 17 | sumo_cfg=sumo_cfg, 18 | is_aircraft_builder_initialized=True, 19 | is_vehicle_builder_initialized=True, 20 | is_traffic_light_builder_initialized=False, 21 | aircraft_inits=aircraft_inits, 22 | num_seconds=num_seconds, 23 | use_gui=use_gui, 24 | is_libsumo=(not use_gui), # 如果不开界面, 就是用 libsumo 25 | ) 26 | 27 | def reset(self): 28 | state_infos = self.tsc_env.reset() 29 | return state_infos 30 | 31 | def step(self, action:Dict[str, Dict[str, int]]): 32 | action = {'aircraft': action} # 这里只控制 aircraft 即可 33 | states, rewards, infos, dones = self.tsc_env.step(action) 34 | truncated = dones 35 | 36 | return states, rewards, truncated, dones, infos 37 | 38 | def close(self) -> None: 39 | self.tsc_env._close_simulation() -------------------------------------------------------------------------------- /benchmark/sumo_envs/J1/add/tls.add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /benchmark/sumo_envs/J1/env/J1.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /benchmark/sumo_envs/OSM/env/osm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/sumo_envs/OSM/env/osm.png -------------------------------------------------------------------------------- /benchmark/sumo_envs/OSM/env/osm.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /benchmark/sumo_envs/OSM/env/viewsettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /benchmark/sumo_envs/multi_junctions_tsc/add/tls.add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /benchmark/sumo_envs/multi_junctions_tsc/env/three_junctions.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /benchmark/sumo_envs/veh_bottleneck/veh.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /benchmark/sumo_envs/veh_rlhf/generate_routes_veh.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-10-27 20:51:49 4 | @Description: 给 Vehicle Lane Change RLHF 环境生成 route 的例子 5 | @LastEditTime: 2023-11-17 16:29:35 6 | ''' 7 | import numpy as np 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.utils.init_log import set_logger 10 | from tshub.sumo_tools.generate_routes import generate_route 11 | 12 | # 初始化日志 13 | current_file_path = get_abs_path(__file__) 14 | set_logger(current_file_path('./')) 15 | 16 | # 开启仿真 --> 指定 net 文件 17 | sumo_net = current_file_path("./veh_rlhf.net.xml") 18 | 19 | # 指定要生成的路口 id 和探测器保存的位置 20 | generate_route( 21 | sumo_net=sumo_net, 22 | interval=[1,2,3], # 有 3 个时间段 23 | edge_flow_per_minute={ 24 | 'E0': [10,20,15], 25 | }, # 每分钟每个 edge 有多少车 26 | edge_turndef={}, 27 | veh_type={ 28 | 'ego': {'color':'26, 188, 156', 'length':7, 'speed':11, 'probability':0.1}, 29 | 'background': {'color':'155, 89, 182', 'speed':6, 'length':7, 'probability':0.9}, 30 | }, 31 | output_trip=current_file_path('./testflow.trip.xml'), 32 | output_turndef=current_file_path('./testflow.turndefs.xml'), 33 | output_route=current_file_path('./veh_rlhf.rou.xml'), 34 | interpolate_flow=False, 35 | interpolate_turndef=False, 36 | ) -------------------------------------------------------------------------------- /benchmark/sumo_envs/veh_rlhf/veh_rlhf.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /benchmark/traffic_light/assets/multi_agents_reward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/traffic_light/assets/multi_agents_reward.png -------------------------------------------------------------------------------- /benchmark/traffic_light/assets/multi_agents_rl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/traffic_light/assets/multi_agents_rl.gif -------------------------------------------------------------------------------- /benchmark/traffic_light/assets/single_agent_reward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/traffic_light/assets/single_agent_reward.png -------------------------------------------------------------------------------- /benchmark/traffic_light/assets/single_agent_rl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/traffic_light/assets/single_agent_rl.gif -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/check_rl_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-10-29 22:46:51 4 | @Description: 多智能体的环境测试 5 | @LastEditTime: 2023-11-01 12:18:56 6 | ''' 7 | from loguru import logger 8 | 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.init_log import set_logger 11 | 12 | from env_utils.make_tsc_env import make_multi_envs 13 | 14 | path_convert = get_abs_path(__file__) 15 | set_logger(path_convert('./')) 16 | 17 | 18 | if __name__ == '__main__': 19 | sumo_cfg = path_convert("../../sumo_envs/multi_junctions_tsc/env/three_junctions.sumocfg") 20 | log_path = path_convert('./log/rl_env') 21 | tsc_env = make_multi_envs( 22 | sumo_cfg=sumo_cfg, 23 | num_seconds=1600, 24 | tls_ids=['J1', 'J2', 'J3'], 25 | use_gui=True, 26 | log_file=log_path, 27 | device='cpu' 28 | ) 29 | 30 | # Simulation with environment 31 | print(f'Group Map: {tsc_env.group_map}') 32 | print(f'Reward Key: {tsc_env.reward_key}') 33 | rollouts = tsc_env.rollout(1_000, break_when_any_done=False) 34 | for r in rollouts: 35 | logger.info(f'RL: {r}') -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/check_rl_parallel_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-10-30 23:01:03 4 | @Description: 检查同时开启多个仿真环境 5 | @LastEditTime: 2023-12-18 20:31:02 6 | ''' 7 | from loguru import logger 8 | 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.init_log import set_logger 11 | from env_utils.make_tsc_env import make_parallel_env 12 | 13 | path_convert = get_abs_path(__file__) 14 | set_logger(path_convert('./')) 15 | 16 | if __name__ == '__main__': 17 | sumo_cfg = path_convert("../../sumo_envs/multi_junctions_tsc/env/three_junctions.sumocfg") 18 | log_path = path_convert('./log/') 19 | tsc_env = make_parallel_env( 20 | num_envs=1, 21 | sumo_cfg=sumo_cfg, 22 | num_seconds=1300, 23 | tls_ids=['J1', 'J2', 'J3'], 24 | use_gui=True, 25 | prefix='check_parallel', 26 | log_file=log_path 27 | ) 28 | 29 | rollouts = tsc_env.rollout(1_000, break_when_any_done=False) 30 | for r in rollouts: 31 | logger.info(f'RL: {r}') -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/env_utils/tsc_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-10-29 23:26:57 4 | @Description: 多路口信号灯控制环境 5 | @LastEditTime: 2023-10-30 15:49:22 6 | ''' 7 | import gymnasium as gym 8 | from typing import List, Dict 9 | from tshub.tshub_env.tshub_env import TshubEnvironment 10 | 11 | class TSCEnvironment(gym.Env): 12 | def __init__( 13 | self, sumo_cfg:str, 14 | num_seconds:int, 15 | tls_ids:List[str], 16 | tls_action_type:str, 17 | use_gui:bool=False 18 | ) -> None: 19 | super().__init__() 20 | 21 | self.tls_ids = tls_ids # 需要控制的路口 ID 22 | self.tsc_env = TshubEnvironment( 23 | sumo_cfg=sumo_cfg, 24 | is_aircraft_builder_initialized=False, 25 | is_vehicle_builder_initialized=True, # 用于获得 vehicle 的 waiting time 来计算 reward 26 | is_traffic_light_builder_initialized=True, 27 | tls_ids=tls_ids, 28 | num_seconds=num_seconds, 29 | tls_action_type=tls_action_type, 30 | use_gui=use_gui, 31 | is_libsumo=(not use_gui), # 如果不开界面, 就是用 libsumo 32 | ) 33 | 34 | def reset(self): 35 | state_infos = self.tsc_env.reset() 36 | return state_infos 37 | 38 | def step(self, action:Dict[str, Dict[str, int]]): 39 | action = {'tls': action} # 这里只控制 tls 即可 40 | states, rewards, infos, dones = self.tsc_env.step(action) 41 | truncated = dones 42 | 43 | return states, rewards, truncated, dones, infos 44 | 45 | def close(self) -> None: 46 | self.tsc_env._close_simulation() -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/eval_mappo.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-10-29 22:47:54 4 | @Description: 测试训练好的 MAPPO 模型 5 | @LastEditTime: 2024-04-25 01:34:20 6 | ''' 7 | import torch 8 | 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.init_log import set_logger 11 | 12 | from train_utils.make_modules import policy_module 13 | from env_utils.make_tsc_env import make_multi_envs 14 | 15 | path_convert = get_abs_path(__file__) 16 | set_logger(path_convert('./')) 17 | 18 | 19 | if __name__ == '__main__': 20 | device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") 21 | sumo_cfg = path_convert("../../sumo_envs/multi_junctions_tsc/env/three_junctions.sumocfg") 22 | log_path = path_convert('./log/eval') 23 | n_agents = 3 24 | 25 | # 1. Create Env 26 | tsc_env = make_multi_envs( 27 | sumo_cfg=sumo_cfg, 28 | num_seconds=1300, 29 | tls_ids=['J1', 'J2', 'J3'], 30 | use_gui=True, 31 | log_file=log_path 32 | ) 33 | 34 | # 2. Load Model Dict 35 | policy_gen = policy_module(tsc_env, n_agents, device) 36 | policy_gen.load_model(path_convert('mappo_models/actor_147.pkl')) 37 | policy = policy_gen.make_policy_module() 38 | 39 | # 3. Simulation with environment using the policy 40 | rollouts = tsc_env.rollout( 41 | policy=policy, 42 | auto_reset=True, 43 | auto_cast_to_device=True, 44 | break_when_any_done=True, 45 | max_steps=1_000 46 | ) -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/log/eval.monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1713981057.4386466} 2 | r,l,t 3 | -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/log/rl_env.monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1713981023.4841964} 2 | r,l,t 3 | -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/log/tsc_pz_env.monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1713963723.6476073} 2 | r,l,t 3 | -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/mappo_tensorboard/events.out.tfevents.1698766231.WMNPower.77672.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/traffic_light/multi_agents/mappo_tensorboard/events.out.tfevents.1698766231.WMNPower.77672.0 -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/plot_rewards.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-01 23:39:42 4 | @Description: 绘制 Reward Curve with Standard Deviation 5 | @LastEditTime: 2024-04-24 23:24:27 6 | ''' 7 | from tshub.utils.plot_reward_curves import plot_reward_curve 8 | from tshub.utils.get_abs_path import get_abs_path 9 | path_convert = get_abs_path(__file__) 10 | 11 | 12 | if __name__ == '__main__': 13 | log_files = [ 14 | path_convert(f'./log/{i}.monitor.csv') 15 | for i in range(6) 16 | ] 17 | output_file = path_convert('./reward.png') 18 | plot_reward_curve(log_files, output_file=output_file, window_size=2) 19 | -------------------------------------------------------------------------------- /benchmark/traffic_light/multi_agents/reward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/traffic_light/multi_agents/reward.png -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/check_tsc_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-08 15:57:34 4 | @Description: 测试 TSC Env 环境 5 | @LastEditTime: 2023-11-01 17:06:21 6 | ''' 7 | import numpy as np 8 | from loguru import logger 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.init_log import set_logger 11 | from stable_baselines3.common.env_checker import check_env 12 | from utils.make_tsc_env import make_env 13 | 14 | path_convert = get_abs_path(__file__) 15 | set_logger(path_convert('./')) 16 | 17 | 18 | if __name__ == '__main__': 19 | sumo_cfg = path_convert("../../sumo_envs/J1/env/J1.sumocfg") 20 | log_path = path_convert('./log/') 21 | tsc_env_generate = make_env( 22 | tls_id='J4', 23 | num_seconds=3600, 24 | sumo_cfg=sumo_cfg, 25 | use_gui=True, 26 | log_file=log_path, 27 | env_index=0, 28 | ) 29 | tsc_env = tsc_env_generate() 30 | 31 | # Check Env 32 | print(tsc_env.observation_space.sample()) 33 | print(tsc_env.action_space.n) 34 | check_env(tsc_env) 35 | 36 | # Simulation with environment 37 | dones = False 38 | tsc_env.reset() 39 | while not dones: 40 | action = np.random.randint(4) 41 | states, rewards, truncated, dones, infos = tsc_env.step(action=action) 42 | logger.info(f"SIM: {infos['step_time']} \n+State:{states}; \n+Reward:{rewards}.") 43 | tsc_env.close() -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/eval_rl_agent.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-08 18:57:35 4 | @Description: 使用训练好的 RL Agent 进行测试 5 | @LastEditTime: 2023-12-21 16:55:51 6 | ''' 7 | import torch 8 | from loguru import logger 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.init_log import set_logger 11 | from stable_baselines3 import PPO 12 | from stable_baselines3.common.vec_env import VecNormalize, SubprocVecEnv 13 | 14 | from utils.make_tsc_env import make_env 15 | 16 | path_convert = get_abs_path(__file__) 17 | logger.remove() 18 | 19 | if __name__ == '__main__': 20 | # ######### 21 | # Init Env 22 | # ######### 23 | sumo_cfg = path_convert("../../sumo_envs/J1/env/J1.sumocfg") 24 | params = { 25 | 'tls_id':'J4', 26 | 'num_seconds': 2000, 27 | 'sumo_cfg':sumo_cfg, 28 | 'use_gui':True, 29 | 'log_file':path_convert('./log/'), 30 | } 31 | env = SubprocVecEnv([make_env(env_index=f'{i}', **params) for i in range(1)]) 32 | env = VecNormalize.load(load_path=path_convert('./models/last_vec_normalize.pkl'), venv=env) 33 | env.training = False # 测试的时候不要更新 34 | env.norm_reward = False 35 | 36 | device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 37 | model_path = path_convert('./models/last_rl_model.zip') 38 | model = PPO.load(model_path, env=env, device=device) 39 | 40 | # 使用模型进行测试 41 | obs = env.reset() 42 | dones = False # 默认是 False 43 | total_reward = 0 44 | 45 | while not dones: 46 | action, _state = model.predict(obs, deterministic=True) 47 | obs, rewards, dones, infos = env.step(action) 48 | total_reward += rewards 49 | 50 | env.close() 51 | print(f'累积奖励为, {total_reward}.') -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/log/0.monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1718721049.842907, "env_id": "None"} 2 | r,l,t 3 | -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/log/1.monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1718721049.725677, "env_id": "None"} 2 | r,l,t 3 | -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/log/2.monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1718721049.7750447, "env_id": "None"} 2 | r,l,t 3 | -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/log/3.monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1718721049.724594, "env_id": "None"} 2 | r,l,t 3 | -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/log/4.monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1718721049.7245784, "env_id": "None"} 2 | r,l,t 3 | -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/log/5.monitor.csv: -------------------------------------------------------------------------------- 1 | #{"t_start": 1718721049.8597445, "env_id": "None"} 2 | r,l,t 3 | -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/models/last_rl_model.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/traffic_light/single_agent/models/last_rl_model.zip -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/models/last_vec_normalize.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/traffic_light/single_agent/models/last_vec_normalize.pkl -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/plot_rewards.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-01 23:46:03 4 | @Description: Reward Curve for Single TSC 5 | @LastEditTime: 2023-11-02 13:28:45 6 | ''' 7 | from tshub.utils.plot_reward_curves import plot_reward_curve 8 | from tshub.utils.get_abs_path import get_abs_path 9 | path_convert = get_abs_path(__file__) 10 | 11 | 12 | if __name__ == '__main__': 13 | log_files = [ 14 | path_convert(f'./log/{i}.monitor.csv') 15 | for i in range(6) 16 | ] 17 | plot_reward_curve(log_files) -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/ruled_method.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-08 19:45:37 4 | @Description: 基于规则的方法, 每次选择排队最大的相位 5 | @LastEditTime: 2023-09-08 20:44:54 6 | ''' 7 | from loguru import logger 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.utils.init_log import set_logger 10 | from utils.make_tsc_env import make_env 11 | 12 | path_convert = get_abs_path(__file__) 13 | set_logger(path_convert('./')) 14 | 15 | 16 | if __name__ == '__main__': 17 | sumo_cfg = path_convert("../../sumo_envs/J1/env/J1.sumocfg") 18 | log_path = path_convert('./log/') 19 | tsc_env_generate = make_env( 20 | tls_id='J4', 21 | num_seconds=2600, 22 | sumo_cfg=sumo_cfg, 23 | use_gui=True, 24 | log_file=log_path, 25 | env_index=0, 26 | ) 27 | tsc_env = tsc_env_generate() 28 | 29 | # Simulation with environment 30 | dones = False 31 | phase_occ = {0:0, 1:0, 2:0, 3:0} 32 | total_reward = 0 33 | tsc_env.reset() 34 | while not dones: 35 | action = max(phase_occ, key=phase_occ.get) 36 | states, rewards, dones, truncated, infos = tsc_env.step(action=action) 37 | total_reward += rewards 38 | phase_occ = infos['phase_occ'] 39 | logger.info(f"SIM: {infos['step_time']} \n+State:{phase_occ};\n+Action:{action}; \n+Reward:{rewards}.") 40 | tsc_env.close() 41 | logger.info(f'累积奖励, {total_reward}.') -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/tensorboard/J1_tensorboard.tfevents: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/benchmark/traffic_light/single_agent/tensorboard/J1_tensorboard.tfevents -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/utils/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-08 15:53:56 4 | @Description: Single Agent Control Example 5 | @LastEditTime: 2023-09-08 15:53:57 6 | ''' 7 | -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/utils/custom_models.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-08 18:34:24 4 | @Description: Custom Model 5 | @LastEditTime: 2023-12-21 17:35:11 6 | ''' 7 | import gym 8 | import torch.nn as nn 9 | from stable_baselines3.common.torch_layers import BaseFeaturesExtractor 10 | 11 | class CustomModel(BaseFeaturesExtractor): 12 | def __init__(self, observation_space: gym.Space, features_dim: int = 16): 13 | """特征提取网络 14 | """ 15 | super().__init__(observation_space, features_dim) 16 | net_shape = observation_space.shape[-1] # 12 17 | 18 | self.embedding = nn.Sequential( 19 | nn.Linear(net_shape, 32), 20 | nn.ReLU(), 21 | ) # 5*12 -> 5*32 22 | 23 | self.lstm = nn.LSTM( 24 | input_size=32, hidden_size=64, 25 | num_layers=1, batch_first=True 26 | ) 27 | self.relu = nn.ReLU() 28 | 29 | self.output = nn.Sequential( 30 | nn.Linear(64, 32), 31 | nn.ReLU(), 32 | nn.Linear(32, features_dim) 33 | ) 34 | 35 | def forward(self, observations): 36 | embedding = self.embedding(observations) 37 | 38 | output, (hn, cn) = self.lstm(embedding) 39 | hn = hn.view(-1, 64) 40 | hn = self.relu(hn) 41 | 42 | output = self.output(hn) 43 | return output -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/utils/make_tsc_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-08 17:45:54 4 | @Description: 创建 TSC Env + Wrapper 5 | @LastEditTime: 2023-09-08 18:25:42 6 | ''' 7 | import gymnasium as gym 8 | from utils.tsc_env import TSCEnvironment 9 | from utils.tsc_wrapper import TSCEnvWrapper 10 | from stable_baselines3.common.monitor import Monitor 11 | 12 | def make_env( 13 | tls_id:str,num_seconds:int,sumo_cfg:str,use_gui:bool, 14 | log_file:str, env_index:int, 15 | ): 16 | def _init() -> gym.Env: 17 | tsc_scenario = TSCEnvironment( 18 | sumo_cfg=sumo_cfg, 19 | num_seconds=num_seconds, 20 | tls_ids=[tls_id], 21 | tls_action_type='choose_next_phase', 22 | use_gui=use_gui, 23 | ) 24 | tsc_wrapper = TSCEnvWrapper(tsc_scenario, tls_id=tls_id) 25 | return Monitor(tsc_wrapper, filename=f'{log_file}/{env_index}') 26 | 27 | return _init -------------------------------------------------------------------------------- /benchmark/traffic_light/single_agent/utils/tsc_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-04 20:43:53 4 | @Description: 信号灯控制环境 5 | @LastEditTime: 2023-09-13 16:15:50 6 | ''' 7 | import gymnasium as gym 8 | 9 | from typing import List, Dict 10 | from tshub.tshub_env.tshub_env import TshubEnvironment 11 | 12 | class TSCEnvironment(gym.Env): 13 | def __init__(self, sumo_cfg:str, num_seconds:int, tls_ids:List[str], tls_action_type:str, use_gui:bool=False) -> None: 14 | super().__init__() 15 | 16 | self.tsc_env = TshubEnvironment( 17 | sumo_cfg=sumo_cfg, 18 | is_aircraft_builder_initialized=False, 19 | is_vehicle_builder_initialized=True, # 用于获得 vehicle 的 waiting time 来计算 reward 20 | is_traffic_light_builder_initialized=True, 21 | tls_ids=tls_ids, 22 | num_seconds=num_seconds, 23 | tls_action_type=tls_action_type, 24 | use_gui=use_gui, 25 | is_libsumo=(not use_gui), # 如果不开界面, 就是用 libsumo 26 | ) 27 | 28 | def reset(self): 29 | state_infos = self.tsc_env.reset() 30 | return state_infos 31 | 32 | def step(self, action:Dict[str, Dict[str, int]]): 33 | action = {'tls': action} # 这里只控制 tls 即可 34 | states, rewards, infos, dones = self.tsc_env.step(action) 35 | truncated = dones 36 | 37 | return states, rewards, truncated, dones, infos 38 | 39 | def close(self) -> None: 40 | self.tsc_env._close_simulation() -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-12-18 17:42:44 4 | @Description: Control Ego Vehicle in Bottleneck 5 | @LastEditTime: 2023-12-18 17:42:46 6 | ''' 7 | -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/check_rl_parallel_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-10-30 23:01:03 4 | @Description: 检查同时开启多个仿真环境 5 | -> 首先设置一个环境, GUI 打开, 查看仿真结束是否正确 6 | -> 接着开启多个仿真, 关闭 GUI, 查看是否可以运行 7 | @LastEditTime: 2023-12-18 22:05:11 8 | ''' 9 | from loguru import logger 10 | from tshub.utils.init_log import set_logger 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from env_utils.make_veh_env import make_parallel_env 13 | 14 | path_convert = get_abs_path(__file__) 15 | set_logger(path_convert('./')) 16 | 17 | if __name__ == '__main__': 18 | sumo_cfg = path_convert("../sumo_envs/veh_bottleneck/veh.sumocfg") 19 | log_path = path_convert('./log/') 20 | 21 | veh_env = make_parallel_env( 22 | num_envs=4, 23 | prefix='check_parallel', 24 | sumo_cfg=sumo_cfg, 25 | warmup_steps=100, # reset 的时候初始的步数 26 | num_seconds=600, # 仿真时间 (这里实际没有被用到) 27 | ego_ids=[ 28 | 'E0__0__ego.1', 29 | 'E0__1__ego.2', 30 | 'E0__2__ego.3', 31 | ], # ego vehicle 的 id 32 | edge_ids=['E0','E1','E2'], 33 | edge_lane_num={ 34 | 'E0':4, 35 | 'E1':4, 36 | 'E2':4 37 | }, # 每一个 edge 对应的车道数 38 | bottle_necks=['E2'], # bottleneck 的 edge id 39 | bottle_neck_positions=(700, 70), # bottle neck 的坐标, 用于计算距离 40 | calc_features_lane_ids=[ 41 | 'E0_0', 'E0_1', 'E0_2', 'E0_3', 42 | 'E1_0', 'E1_1', 'E1_2', 'E1_3', 43 | 'E2_0', 'E2_1', 'E2_2', 'E2_3', 44 | ], # 计算对应的 lane 的信息 45 | use_gui=False, 46 | log_file=log_path 47 | ) 48 | 49 | rollouts = veh_env.rollout(1_000, break_when_any_done=False) 50 | for r in rollouts: 51 | logger.info(f'RL: {r}') -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/env_utils/__Init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-12-17 21:48:14 4 | @Description: Ego Vehicle Speed Environment 5 | @LastEditTime: 2023-12-17 21:48:15 6 | ''' 7 | -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/env_utils/veh_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: Liu Lu & WANG Maonan 3 | @Date: 2023-10-27 20:16:40 4 | @Description: 基础车辆环境 5 | @LastEditTime: 2023-12-16 22:22:16 6 | ''' 7 | import gymnasium as gym 8 | 9 | from typing import Dict 10 | from tshub.tshub_env.tshub_env import TshubEnvironment 11 | 12 | class VehEnvironment(gym.Env): 13 | def __init__(self, 14 | sumo_cfg:str, num_seconds:int, 15 | vehicle_action_type:str, use_gui:bool=False, 16 | trip_info: str = None # 添加 trip_info 参数 17 | 18 | ) -> None: 19 | super().__init__() 20 | self.num_seconds = num_seconds # 将 num_seconds 保存为一个属性 21 | 22 | self.tsc_env = TshubEnvironment( 23 | sumo_cfg=sumo_cfg, 24 | is_vehicle_builder_initialized=True, # 只需要获得车辆的信息 25 | is_aircraft_builder_initialized=False, 26 | is_traffic_light_builder_initialized=False, 27 | is_map_builder_initialized=False, 28 | is_person_builder_initialized=False, 29 | vehicle_action_type=vehicle_action_type, 30 | num_seconds=num_seconds, 31 | use_gui=use_gui, 32 | is_libsumo=(not use_gui), # 如果不开界面, 就是用 libsumo 33 | trip_info=trip_info 34 | ) 35 | 36 | def reset(self): 37 | state_infos = self.tsc_env.reset() 38 | return state_infos 39 | 40 | def step(self, action:Dict[str, Dict[str, int]]): 41 | action = {'vehicle': action} 42 | states, rewards, infos, dones = self.tsc_env.step(action) 43 | truncated = dones 44 | 45 | return states, rewards, truncated, dones, infos 46 | 47 | def close(self) -> None: 48 | self.tsc_env._close_simulation() -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/plot_rewards.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-01 23:39:42 4 | @Description: 绘制 Reward Curve with Standard Deviation 5 | @LastEditTime: 2023-11-02 13:28:31 6 | ''' 7 | from tshub.utils.plot_reward_curves import plot_reward_curve 8 | from tshub.utils.get_abs_path import get_abs_path 9 | path_convert = get_abs_path(__file__) 10 | 11 | 12 | if __name__ == '__main__': 13 | log_files = [ 14 | path_convert(f'./log/train_{i}.monitor.csv') 15 | for i in range(6) 16 | ] 17 | plot_reward_curve(log_files) 18 | -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/single_agent/plot_rewards.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-01 23:46:03 4 | @Description: Reward Curve for Single TSC 5 | @LastEditTime: 2023-11-02 13:28:45 6 | ''' 7 | from tshub.utils.plot_reward_curves import plot_reward_curve 8 | from tshub.utils.get_abs_path import get_abs_path 9 | path_convert = get_abs_path(__file__) 10 | 11 | 12 | if __name__ == '__main__': 13 | log_files = [ 14 | path_convert(f'./log/{i}.monitor.csv') 15 | for i in range(6) 16 | ] 17 | plot_reward_curve(log_files) -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/single_agent/utils/__Init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-12-17 21:48:14 4 | @Description: Ego Vehicle Speed Environment 5 | @LastEditTime: 2023-12-17 21:48:15 6 | ''' 7 | -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/single_agent/utils/custom_models.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-08 18:34:24 4 | @Description: Custom Model 5 | @LastEditTime: 2023-12-21 17:35:11 6 | ''' 7 | import gym 8 | import torch.nn as nn 9 | from stable_baselines3.common.torch_layers import BaseFeaturesExtractor 10 | 11 | class CustomModel(BaseFeaturesExtractor): 12 | def __init__(self, observation_space: gym.Space, features_dim: int = 16): 13 | """特征提取网络 14 | """ 15 | super().__init__(observation_space, features_dim) 16 | net_shape = observation_space.shape[-1] # 12 17 | 18 | self.embedding = nn.Sequential( 19 | nn.Linear(net_shape, 128), 20 | nn.ReLU(), 21 | ) # 5*12 -> 5*32 22 | 23 | self.output = nn.Sequential( 24 | nn.Linear(128, 64), 25 | nn.ReLU(), 26 | nn.Linear(64, 32), 27 | nn.ReLU(), 28 | nn.Linear(32, features_dim) 29 | ) 30 | 31 | def forward(self, observations): 32 | embedding = self.embedding(observations) 33 | 34 | output = self.output(embedding) 35 | return output -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/single_agent/utils/make_veh_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-12-21 14:42:14 4 | @Description: veh_env + veh_wrapper 5 | @LastEditTime: 2023-12-21 16:37:35 6 | ''' 7 | import gymnasium as gym 8 | 9 | from typing import List, Dict, Tuple 10 | from utils.veh_env import VehEnvironment 11 | from utils.veh_wrapper import VehEnvWrapper 12 | from stable_baselines3.common.monitor import Monitor 13 | 14 | def make_env( 15 | sumo_cfg:str, 16 | num_seconds:int, warmup_steps:int, 17 | ego_ids:List[str], out_edge_ids:List[str], bottle_necks:List[str], 18 | bottle_neck_positions:Tuple[int], 19 | calc_features_lane_ids:List[str], use_gui:bool, 20 | log_file:str, env_index:int, 21 | trip_info:str=None 22 | ): 23 | def _init() -> gym.Env: 24 | veh_env = VehEnvironment( 25 | sumo_cfg=sumo_cfg, 26 | num_seconds=num_seconds, 27 | vehicle_action_type='lane_continuous_speed', 28 | use_gui=use_gui, 29 | trip_info=trip_info, 30 | ) 31 | tsc_wrapper = VehEnvWrapper( 32 | env=veh_env, 33 | warmup_steps=warmup_steps, 34 | ego_ids=ego_ids, 35 | out_edge_ids=out_edge_ids, 36 | bottle_necks=bottle_necks, 37 | bottle_neck_positions=bottle_neck_positions, 38 | calc_features_lane_ids=calc_features_lane_ids 39 | ) 40 | return Monitor(tsc_wrapper, filename=f'{log_file}/{env_index}') 41 | 42 | return _init -------------------------------------------------------------------------------- /benchmark/vehicle_bottleneck/single_agent/utils/veh_env.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: Liu Lu & WANG Maonan 3 | @Date: 2023-10-27 20:16:40 4 | @Description: 基础车辆环境 5 | @LastEditTime: 2023-12-16 22:22:16 6 | ''' 7 | import gymnasium as gym 8 | 9 | from typing import Dict 10 | from tshub.tshub_env.tshub_env import TshubEnvironment 11 | 12 | class VehEnvironment(gym.Env): 13 | def __init__(self, 14 | sumo_cfg:str, num_seconds:int, 15 | vehicle_action_type:str, use_gui:bool=False, 16 | trip_info: str = None # 添加 trip_info 参数 17 | 18 | ) -> None: 19 | super().__init__() 20 | self.num_seconds = num_seconds # 将 num_seconds 保存为一个属性 21 | 22 | self.tsc_env = TshubEnvironment( 23 | sumo_cfg=sumo_cfg, 24 | is_vehicle_builder_initialized=True, # 只需要获得车辆的信息 25 | is_aircraft_builder_initialized=False, 26 | is_traffic_light_builder_initialized=False, 27 | is_map_builder_initialized=False, 28 | is_person_builder_initialized=False, 29 | vehicle_action_type=vehicle_action_type, 30 | num_seconds=num_seconds, 31 | use_gui=use_gui, 32 | is_libsumo=(not use_gui), # 如果不开界面, 就是用 libsumo 33 | trip_info=trip_info 34 | ) 35 | 36 | def reset(self): 37 | state_infos = self.tsc_env.reset() 38 | return state_infos 39 | 40 | def step(self, action:Dict[str, Dict[str, int]]): 41 | action = {'vehicle': action} 42 | states, rewards, infos, dones = self.tsc_env.step(action) 43 | truncated = dones 44 | 45 | return states, rewards, truncated, dones, infos 46 | 47 | def close(self) -> None: 48 | self.tsc_env._close_simulation() -------------------------------------------------------------------------------- /docs/.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the OS, Python version and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the "docs/" directory with Sphinx 19 | sphinx: 20 | configuration: docs/source/conf.py 21 | 22 | # Optionally build your docs in additional formats such as PDF and ePub 23 | # formats: 24 | # - pdf 25 | # - epub 26 | 27 | # Optional but recommended, declare the Python requirements required 28 | # to build your documentation 29 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 30 | python: 31 | install: 32 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx_rtd_theme -------------------------------------------------------------------------------- /docs/source/_static/object/aircraft_action.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/object/aircraft_action.gif -------------------------------------------------------------------------------- /docs/source/_static/object/single_junction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/object/single_junction.png -------------------------------------------------------------------------------- /docs/source/_static/object/traffic_light_example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/object/traffic_light_example.gif -------------------------------------------------------------------------------- /docs/source/_static/object/vehicle_example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/object/vehicle_example.gif -------------------------------------------------------------------------------- /docs/source/_static/stepbystep_tutorial/create_scenario/background_view_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/stepbystep_tutorial/create_scenario/background_view_setting.png -------------------------------------------------------------------------------- /docs/source/_static/stepbystep_tutorial/create_scenario/create_scenario_flow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/stepbystep_tutorial/create_scenario/create_scenario_flow.gif -------------------------------------------------------------------------------- /docs/source/_static/stepbystep_tutorial/create_scenario/osm_export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/stepbystep_tutorial/create_scenario/osm_export.png -------------------------------------------------------------------------------- /docs/source/_static/stepbystep_tutorial/create_scenario/sumo_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/stepbystep_tutorial/create_scenario/sumo_net.png -------------------------------------------------------------------------------- /docs/source/_static/stepbystep_tutorial/create_scenario/sumonet_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/stepbystep_tutorial/create_scenario/sumonet_background.png -------------------------------------------------------------------------------- /docs/source/_static/sumo_tools/detector_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/sumo_tools/detector_add.png -------------------------------------------------------------------------------- /docs/source/_static/sumo_tools/e2_detectors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/sumo_tools/e2_detectors.png -------------------------------------------------------------------------------- /docs/source/_static/sumo_tools/flow_interpolation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/sumo_tools/flow_interpolation.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/aircraft/follow_vehicle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/aircraft/follow_vehicle.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/aircraft/horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/aircraft/horizontal.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/aircraft/vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/aircraft/vertical.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/junction/junction_back.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/junction/junction_back.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/junction/junction_back_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/junction/junction_back_example.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/junction/junction_front.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/junction/junction_front.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/junction/junction_front_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/junction/junction_front_example.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/traffic_scenario/sumo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/traffic_scenario/sumo.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/traffic_scenario/tshub3d.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/traffic_scenario/tshub3d.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego0_all.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego0_all.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego0_vehicle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego0_vehicle.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego1_all.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego1_all.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego1_vehicle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego1_vehicle.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego2_all.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego2_all.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego2_vehicle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle/vehicle_ego2_vehicle.gif -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle/vehicle_sensor_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle/vehicle_sensor_example.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/emergency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/emergency.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/fire_engine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/fire_engine.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/police.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/police.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/suv_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/suv_blue.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/suv_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/suv_grey.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/suv_orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/suv_orange.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/taxi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/taxi.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/vehicle_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/vehicle_blue.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/vehicle_pink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/vehicle_pink.png -------------------------------------------------------------------------------- /docs/source/_static/tshub3d_sensors/vehicle_types/vehicle_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/tshub3d_sensors/vehicle_types/vehicle_white.png -------------------------------------------------------------------------------- /docs/source/_static/v2x/packet_loss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/docs/source/_static/v2x/packet_loss.png -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-30 20:41:24 4 | @Description: TransSimHub Documentation 5 | @LastEditTime: 2024-08-10 20:49:36 6 | ''' 7 | # Configuration file for the Sphinx documentation builder. 8 | # 9 | # For the full list of built-in configuration values, see the documentation: 10 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 11 | 12 | # -- Project information ----------------------------------------------------- 13 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 14 | 15 | project = 'TransSimHub' 16 | copyright = '2023, Traffic-Alpha' 17 | author = 'Traffic-Alpha' 18 | release = '0.9' 19 | 20 | # -- General configuration --------------------------------------------------- 21 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 22 | 23 | extensions = [ 24 | 'sphinx.ext.autodoc', 25 | 'sphinx.ext.viewcode', 26 | 'sphinx.ext.githubpages', 27 | ] 28 | 29 | templates_path = ['_templates'] 30 | exclude_patterns = [] 31 | 32 | 33 | 34 | # -- Options for HTML output ------------------------------------------------- 35 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 36 | 37 | html_theme = 'sphinx_rtd_theme' 38 | html_static_path = ['_static'] 39 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. TransSimHub documentation master file, created by 2 | sphinx-quickstart on Wed Aug 30 20:41:24 2023. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to TransSimHub's documentation! 7 | ======================================= 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | locales/en/index 14 | locales/zh_CN/index 15 | 16 | 17 | Indices and tables 18 | ================== 19 | 20 | * :ref:`genindex` 21 | * :ref:`modindex` 22 | * :ref:`search` 23 | -------------------------------------------------------------------------------- /docs/source/locales/en/index.rst: -------------------------------------------------------------------------------- 1 | TransSimHub Documentation 2 | =============================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Table of Content 7 | 8 | introduction/index 9 | installation/index 10 | tshub3d_sensors/index -------------------------------------------------------------------------------- /docs/source/locales/en/introduction/index.rst: -------------------------------------------------------------------------------- 1 | .. _introduction: 2 | 3 | TransSimHub Introduction 4 | =========================== 5 | 6 | TransSimHub (TSHub) is a Python library for simulating air-land traffic using SUMO. It provides a range of powerful tools and models for scenario creation, real-time retrieval, and control of vehicles, aircraft, and traffic lights. 7 | 8 | Key Features 9 | ------------ 10 | 11 | - **Scenario Creation**: Includes automated tools for generating mixed traffic flows and laying out detectors at intersections. 12 | - **Air-Land Integration**: Provides interfaces for retrieving information and controlling vehicles, aircraft, and traffic lights. 13 | - **Reinforcement Learning Support**: TransSimHub is compatible with the Gym library interface and integrates with the rllib reinforcement learning framework. 14 | 15 | With TransSimHub, you can easily create complex scenarios, interact with vehicles and aircraft in real-time, and leverage reinforcement learning algorithms for advanced control and optimization. 16 | 17 | Installation 18 | ------------ 19 | 20 | To install TransSimHub, please refer to the :doc:`../installation/index` section. 21 | 22 | Next, let's explore the capabilities of TransSimHub and learn how to use it effectively. 23 | 24 | .. note:: 25 | If you encounter any issues during the installation process or while using TransSimHub, refer to the project's documentation or seek help from the community. 26 | -------------------------------------------------------------------------------- /docs/source/locales/en/tshub3d_sensors/index.rst: -------------------------------------------------------------------------------- 1 | TransSimHub 3D Rendering 2 | ============================= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Objects 7 | 8 | traffic_scenario 9 | vehicle_types 10 | junction 11 | vehicle 12 | aircraft 13 | -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/index.rst: -------------------------------------------------------------------------------- 1 | TransSimHub 中文文档 2 | ========================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录 7 | 8 | introduction/index 9 | installation/index 10 | sumo_tools/index 11 | object/index 12 | tshub3d_sensors/index 13 | v2x/index 14 | stepbystep_tutorial/index -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/installation/index.rst: -------------------------------------------------------------------------------- 1 | .. _install: 2 | 3 | TransSimHub 安装 4 | ===================== 5 | 6 | 通过 GitHub 安装 7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 | 9 | 您可以通过 GitHub 源码来安装 `TransSimHub`,请按照以下步骤操作: 10 | 11 | 1. 克隆 GitHub 仓库: 12 | 13 | .. code-block:: bash 14 | 15 | git clone https://github.com/Traffic-Alpha/TransSimHub.git 16 | cd TransSimHub 17 | 18 | 2. 使用 pip 安装: 19 | 20 | .. code-block:: bash 21 | 22 | pip install -e . 23 | 24 | 安装完成后,您可以使用以下Python命令检查TransSimHub是否安装成功,并查看其版本号: 25 | 26 | .. code-block:: python 27 | 28 | import tshub 29 | print(tshub.__version__) 30 | 31 | 32 | 特殊版本 33 | ~~~~~~~~~~~~ 34 | 35 | 如果您希望启用 TransSimHub 的额外功能并安装相关依赖,请添加额外的参数。例如加上 doc 可以启动 TransSimHub 的文档编辑: 36 | 37 | .. code-block:: bash 38 | 39 | # 安装Sphinx和相关包 40 | pip install -U -e ".[doc]" 41 | 42 | 如果希望一次性将 **所有的依赖** 全部安装完毕,强烈建议使用参数 **all**,如下所示: 43 | 44 | .. code-block:: bash 45 | 46 | pip install -U -e ".[all]" 47 | 48 | 请注意,这可能需要一些额外的时间和资源来安装和构建所需的依赖项。 49 | 50 | 通过按照上述步骤,您将成功安装 TransSimHub,并准备好在Python环境中使用它。 51 | 52 | .. note:: 53 | 如果在安装过程中遇到任何问题,请参考项目的GitHub仓库进行故障排除,或向项目的社区寻求帮助。 54 | 55 | 接下来,让我们了解如何在您的项目中使用TransSimHub。 56 | -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/introduction/index.rst: -------------------------------------------------------------------------------- 1 | .. _introduction: 2 | 3 | TransSimHub 介绍 4 | ===================== 5 | 6 | TransSimHub(TSHub)是一个基于 SUMO 的 Python 库,用于模拟空天地交通。它提供了一系列功能强大的工具和模型,用于场景创建、实时获取和控制车辆、飞机和交通信号灯。 7 | 8 | 主要功能 9 | ~~~~~~~~~~~~~~ 10 | 11 | - **场景创建**:包括自动化工具,用于生成混合交通流并在交叉口布置探测器。 12 | - **空天地一体化**:提供了用于获取信息和控制车辆、飞机和交通信号灯的接口。 13 | - **强化学习支持**:TransSimHub 与 Gym 库接口兼容,并与 rllib 等强化学习框架集成。 14 | 15 | 通过TransSimHub,您可以轻松创建复杂的场景,实时与车辆和飞机进行交互,并利用强化学习算法进行高级控制和优化。 16 | 17 | 安装 18 | ~~~~~~~~~~~ 19 | 20 | 要安装 TransSimHub,请参考 :doc:`../installation/index` 部分。 21 | 22 | 23 | 接下来,让我们探索 TransSimHub 的功能,并学习如何有效地使用它。 24 | 25 | .. note:: 26 | 如果在安装过程中或使用 TransSimHub 时遇到任何问题,请参考项目的文档或向社区寻求帮助。 27 | 28 | -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/object/index.rst: -------------------------------------------------------------------------------- 1 | TransSimHub Objects 2 | ======================= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Objects 7 | 8 | aircraft 9 | vehicle 10 | traffic_light -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/stepbystep_tutorial/index.rst: -------------------------------------------------------------------------------- 1 | TransSimHub 使用例子 2 | =============================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Objects 7 | 8 | create_scenario -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/sumo_tools/index.rst: -------------------------------------------------------------------------------- 1 | TransSimHub 场景创建 2 | ======================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Objects 7 | 8 | tls_addition 9 | generate_detectors 10 | generate_routes -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/tshub3d_sensors/aircraft.rst: -------------------------------------------------------------------------------- 1 | 飞行器 RGB 传感器 2 | =================== 3 | 4 | 在 TSHub3D 的模拟环境中,飞行器搭载的 RGB 传感器为交通监控和自动驾驶研究提供了一个独特的视角。本节将详细介绍三种不同飞行模式的飞行器传感器效果。 5 | 6 | 飞行器垂直方向飞行 7 | ----------------------- 8 | 9 | 垂直飞行模式的飞行器可以在垂直方向上升和下降,从而改变拍摄角度和视野范围。随着飞行器上升,可观察到的区域范围扩大,但同时物体的细节将变得不那么清晰。相反,当飞行器下降时,可以捕获到更多的细节信息。 10 | 11 | .. figure:: ../../../_static/tshub3d_sensors/aircraft/vertical.gif 12 | :alt: 飞行器垂直方向飞行效果 13 | :align: center 14 | 15 | 飞行器垂直方向飞行效果。图中展示了飞行器上升和下降时视角的变化。 16 | 17 | 飞行器水平面飞行 18 | ----------------------- 19 | 20 | 在水平面飞行模式中,飞行器围绕路口进行旋转飞行,这使得我们能够从多个角度动态地观察到路口周围的情况。 21 | 22 | .. figure:: ../../../_static/tshub3d_sensors/aircraft/horizontal.gif 23 | :alt: 飞行器水平面飞行效果 24 | :align: center 25 | 26 | 飞行器水平面飞行效果。图中显示了飞行器围绕路口旋转时捕捉到的连续画面。 27 | 28 | 飞行器跟车 29 | ------------------- 30 | 31 | 第三种模式是飞行器跟随特定车辆飞行,这样可以从空中密切观察和记录车辆的周围环境及其交互情况。 32 | 33 | .. figure:: ../../../_static/tshub3d_sensors/aircraft/follow_vehicle.gif 34 | :alt: 飞行器跟车效果 35 | :align: center 36 | 37 | 飞行器跟车效果。图中展示了飞行器跟随车辆时的视角和捕捉到的信息。 38 | 39 | 通过这些传感器配置,TSHub3D 为研究者提供了一个全方位的交通监控工具,不仅能够从地面车辆的视角分析交通情况,还能从空中视角提供补充信息,有助于深入理解交通流和驾驶行为。 40 | -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/tshub3d_sensors/index.rst: -------------------------------------------------------------------------------- 1 | TransSimHub 3D 渲染 2 | ============================= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Objects 7 | 8 | traffic_scenario 9 | vehicle_types 10 | junction 11 | vehicle 12 | aircraft 13 | -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/tshub3d_sensors/junction.rst: -------------------------------------------------------------------------------- 1 | 路口 RGB 传感器 2 | ======================= 3 | 4 | TSHub3D 提供了全方位的路口监控功能,通过在十字路口的每个进入方向部署 **前拍** 和 **后拍** 传感器,从而实现全面的交通路口监控。以下是前拍和后拍传感器的详细介绍以及它们捕获的效果。 5 | 6 | 前拍传感器 7 | -------------------- 8 | 9 | 前拍传感器主要负责拍摄车辆的前部,能够有效地捕捉到车辆的前方情况以及车道的排队状况。下面的图片展示了一个前拍传感器的示例图像。 10 | 11 | .. figure:: ../../../_static/tshub3d_sensors/junction/junction_front_example.png 12 | :alt: 前拍传感器示例 13 | :align: center 14 | :figwidth: 75% 15 | 16 | 前拍传感器示例。图中显示了车辆的前部以及车道的排队情况。 17 | 18 | 接下来,我们看到的是 TSHub3D 中前拍传感器捕获的动态效果。这些图像可以用于交通监控分析,也可以作为自动驾驶系统模型训练的标签数据。 19 | 20 | .. figure:: ../../../_static/tshub3d_sensors/junction/junction_front.gif 21 | :alt: 前拍传感器捕获效果 22 | :align: center 23 | 24 | 前拍传感器捕获效果。图中展示了四个不同方向的前拍传感器捕获的场景和车辆信息。 25 | 26 | 27 | 后拍传感器 28 | -------------------- 29 | 30 | 后拍传感器则是专注于捕捉车辆的尾部,这对于判断车辆行驶方向(直行或转弯)非常有帮助。同时,后拍传感器也能够观测到路口对面车道的交通状况。以下是后拍传感器的示例图像。 31 | 32 | .. figure:: ../../../_static/tshub3d_sensors/junction/junction_back_example.png 33 | :alt: 后拍传感器示例 34 | :align: center 35 | :figwidth: 75% 36 | 37 | 后拍传感器示例。图中显示了车辆的后部以及路口对面车道的排队情况。 38 | 39 | 下面的动态图展示了 TSHub3D 中后拍传感器捕获的效果。与前拍传感器类似,后拍传感器也提供了全方位的监控视角。 40 | 41 | .. figure:: ../../../_static/tshub3d_sensors/junction/junction_back.gif 42 | :alt: 后拍传感器捕获效果 43 | :align: center 44 | 45 | 后拍传感器捕获效果。图中展示了四个不同方向的后拍传感器捕获的完整场景和车辆信息。 46 | 47 | 通过结合前拍和后拍传感器,TSHub3D 能够提供一个十字路口全面的交通监控解决方案,这对于交通流量分析、事故预防以及自动驾驶算法的开发具有重要意义。 -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/tshub3d_sensors/traffic_scenario.rst: -------------------------------------------------------------------------------- 1 | TransSimHub 3D 渲染 2 | =========================== 3 | 4 | 在本节中,我们将介绍如何使用 TransSimHub (TSHub) 来创建和渲染一个交通模拟的三维场景。我们的示例场景是一个 **标准的单十字路口**,其中包括: 5 | 6 | * 三辆自动驾驶车辆(ego vehicle); 7 | * 两个飞行器(aircraft):一个垂直飞行的飞行器和一个水平飞行的飞行器; 8 | 9 | 10 | SUMO 可视化 11 | -------------------- 12 | 13 | 首先我们使用 SUMO 来展示十字路口的交通流动情况。如下图所示,你可以看到车辆在路口的通行情况,以及在路口上空进行飞行任务的两个飞行器。其中,水平飞行的无人机保持通信半径大小不变,而垂直飞行的无人机则根据高度变化调整其通信范围。 14 | 15 | .. figure:: ../../../_static/tshub3d_sensors/traffic_scenario/sumo.gif 16 | :alt: SUMO 模拟效果图 17 | :align: center 18 | :figwidth: 75% 19 | 20 | SUMO模拟效果图。图中展示了十字路口的车辆通行以及无人机的飞行状态。 21 | 22 | TSHub3D 可视化 23 | ---------------------- 24 | 25 | 接下来,我们使用 **TSHub 3D** 来进行三维可视化。TSHub 3D 允许我们将传感器放置在场景中的任意位置,从而捕捉到不同角度的视觉效果。如下图所示,我们将传感器部署在路口上方并围绕路口渲染,以获取更加生动和真实的三维视觉效果。 26 | 27 | .. figure:: ../../../_static/tshub3d_sensors/traffic_scenario/tshub3d.gif 28 | :alt: TSHub3D 可视化效果图 29 | :align: center 30 | :figwidth: 75% 31 | 32 | TSHub3D 可视化效果图。图中显示了传感器捕捉的三维场景,包括车道、车道线和路口的车辆。 33 | 34 | 在上述可视化中,我们可以清晰地看到每个车辆的位置,以及它们在模拟环境中的动态交互。TSHub 3D 的这些功能对于交通研究和自动驾驶系统的开发至关重要,它们提供了一个强大的工具来将交通场景进行 3D 的展示。 35 | -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/v2x/index.rst: -------------------------------------------------------------------------------- 1 | V2X 通信 2 | ========= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Objects 7 | 8 | v2x 9 | outage_probability -------------------------------------------------------------------------------- /docs/source/locales/zh_CN/v2x/outage_probability.rst: -------------------------------------------------------------------------------- 1 | 中断概率 (Outage Probability) 2 | ========================================= 3 | 4 | 中断概率是指在给定的目标速率下,当前信道容量小于该速率的概率。 5 | 6 | 在瑞利衰落信道的假设下,信道的功率衰减量 :math:`\mu = |h|^2` 服从参数为 1 的指数分布。因此,中断概率 :math:`P_{\text{out}}(R)` 可以表示为: 7 | 8 | .. math:: 9 | 10 | \begin{align*} 11 | P_{\text{out}}(R) &= \Pr\left(\mu < \frac{2^R - 1}{SNR_t}\right) \\ 12 | &= \int_0^{\frac{2^R - 1}{SNR_t}} e^{-u} \, du \\ 13 | &= 1 - \exp\left(-\frac{2^R - 1}{SNR_t}\right) 14 | \end{align*} 15 | 16 | 其中: 17 | 18 | - :math:`R` 是给定的目标速率(单位:比特/秒/赫兹) 19 | - :math:`SNR_t` 是该时刻的信噪比(单位:分贝) 20 | 21 | 22 | 23 | 中断概率例子 24 | --------------- 25 | 26 | 例如,假设信道带宽为 30 kHz,目标速率为 20 kb/s,信噪比 \( SNR \) 为 10 dB,我们可以计算中断概率为: 27 | 28 | .. math:: 29 | 30 | 1 - \exp\left(-\frac{2^{\frac{20 \times 10^3}{30 \times 10^3}} - 1}{10}\right) \approx 0.057 31 | 32 | 这个结果表明,在当前的信噪比下,有大约 5.7% 的概率会发生中断。 33 | 34 | 下图展示了在信道带宽为 30 kHz,目标速率为 20 kb/s 的时候,中断概率与 SNR 的关系。可以看到 SNR 越大,中断概率越低。 35 | 36 | 37 | .. figure:: ../../../_static/v2x/packet_loss.png 38 | :alt: Packet Loss 和 SNR 的关系 39 | :align: center -------------------------------------------------------------------------------- /examples/aircraft/aircraft_actions/aircraft_stationary.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-24 12:03:53 4 | @Description: Aircraft 静止 5 | @LastEditTime: 2023-09-14 16:25:55 6 | ''' 7 | import traci 8 | import sumolib 9 | from loguru import logger 10 | 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.aircraft.aircraft_builder import AircraftBuilder 13 | from tshub.utils.init_log import set_logger 14 | from tshub.utils.format_dict import dict_to_str 15 | 16 | sumoBinary = sumolib.checkBinary('sumo-gui') 17 | 18 | path_convert = get_abs_path(__file__) 19 | set_logger(path_convert('./')) 20 | 21 | sumocfg_file = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 22 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 23 | conn = traci.getConnection('0') 24 | 25 | aircraft_inits = { 26 | 'a1': { 27 | "aircraft_type": "drone", 28 | "action_type": "stationary", 29 | "position":(1500,1110,100), "speed":10, "heading":(1,1,0), "communication_range":200, 30 | "if_sumo_visualization":True, "img_file":None}, 31 | 'a2': { 32 | "aircraft_type": "drone", 33 | "action_type": "stationary", 34 | "position":(1900,800,100), "speed":10, "heading":(1,1,0), "communication_range":200, 35 | "if_sumo_visualization":True, "img_file":None 36 | } 37 | } 38 | 39 | scene_aircraft = AircraftBuilder(sumo=conn, aircraft_inits=aircraft_inits) 40 | while conn.simulation.getMinExpectedNumber() > 0: 41 | conn.simulationStep() # 仿真到某一步 42 | actions = { 43 | "a1": (1, 1), 44 | "a2": (1, 1), 45 | } # 这里的 action 不会移动 aircraft 46 | scene_aircraft.control_objects(actions) 47 | aircraft_state = scene_aircraft.get_objects_infos() 48 | logger.info(f'SIM: {dict_to_str(aircraft_state)}') 49 | 50 | conn.close() -------------------------------------------------------------------------------- /examples/aircraft/get_aircraft_state.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 20:21:16 4 | @Description: 测试获得 AirCraft 的信息 5 | @LastEditTime: 2023-09-14 16:31:48 6 | ''' 7 | from loguru import logger 8 | from tshub.aircraft.aircraft_builder import AircraftBuilder 9 | from tshub.utils.format_dict import dict_to_str 10 | 11 | aircraft_inits = { 12 | 'a1': { 13 | "aircraft_type": "drone", 14 | "action_type": "horizontal_movement", 15 | "position":(10,10,50), "speed":10, "heading":(1,1,0), "communication_range":100 16 | }, 17 | 'a2': { 18 | "aircraft_type": "drone", 19 | "action_type": "horizontal_movement", 20 | "position":(10,10,50), "speed":10, "heading":(1,1,0), "communication_range":100 21 | } 22 | } 23 | 24 | scene_aircraft = AircraftBuilder( 25 | sumo=None, 26 | aircraft_inits=aircraft_inits 27 | ) 28 | aircraft_state = scene_aircraft.get_objects_infos() 29 | logger.info(dict_to_str(aircraft_state)) -------------------------------------------------------------------------------- /examples/map/get_grid_info.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-05-29 15:01:25 4 | @Description: 将地图划分为 grid, 获得每个 grid 每个座标点的信息, 例如 SNR 5 | @LastEditTime: 2024-05-29 16:37:55 6 | ''' 7 | from loguru import logger 8 | 9 | from tshub.map.map_builder import MapBuilder 10 | from tshub.utils.get_abs_path import get_abs_path 11 | from tshub.utils.init_log import set_logger 12 | from tshub.utils.format_dict import dict_to_str 13 | 14 | path_convert = get_abs_path(__file__) 15 | set_logger(path_convert('./')) 16 | 17 | net_file = path_convert("../sumo_env/berlin_UAM/berlin_UAM.net.xml") 18 | snir_file = path_convert("../sumo_env/berlin_UAM/berlin_UAM_SNIR_100.txt") 19 | 20 | map_builder = MapBuilder( 21 | net_file=net_file, 22 | radio_map_files={'SNIR_100': snir_file} 23 | ) 24 | map_infos = map_builder.get_objects_infos() 25 | # 获得信息 26 | map_infos['grid']['SNIR_100'].get_value_at_coordinate(500, 1000) # 获得每一个点的信息 27 | map_infos['grid']['SNIR_100'].grid_z # 获得地图的信息 28 | logger.info(f'SIM: \n{dict_to_str(map_infos)}') -------------------------------------------------------------------------------- /examples/map/get_net_info.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-12 14:48:21 4 | @Description: 只获取 net 的信息, 包含 edge 和 node 的 shape 5 | @LastEditTime: 2024-04-09 22:52:44 6 | ''' 7 | from loguru import logger 8 | 9 | from tshub.map.map_builder import MapBuilder 10 | from tshub.utils.get_abs_path import get_abs_path 11 | from tshub.utils.init_log import set_logger 12 | from tshub.utils.format_dict import dict_to_str 13 | 14 | path_convert = get_abs_path(__file__) 15 | set_logger(path_convert('./')) 16 | 17 | net_file = path_convert("../sumo_env/osm_berlin/env/berlin.net.xml") 18 | 19 | map_builder = MapBuilder( 20 | net_file=net_file, 21 | ) 22 | map_infos = map_builder.get_objects_infos() 23 | logger.info(f'SIM: \n{dict_to_str(map_infos)}') -------------------------------------------------------------------------------- /examples/map/get_poly_info.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-22 14:38:20 4 | @Description: 获得地图中所有的 Polygon 的信息 5 | @LastEditTime: 2023-11-12 14:27:30 6 | ''' 7 | from loguru import logger 8 | 9 | from tshub.map.map_builder import MapBuilder 10 | from tshub.utils.get_abs_path import get_abs_path 11 | from tshub.utils.init_log import set_logger 12 | from tshub.utils.format_dict import dict_to_str 13 | 14 | path_convert = get_abs_path(__file__) 15 | set_logger(path_convert('./')) 16 | 17 | net_file = path_convert("../sumo_env/osm_berlin/env/berlin.net.xml") 18 | poly_file = path_convert("../sumo_env/osm_berlin/env/berlin.poly.xml") 19 | osm_file = path_convert("../sumo_env/osm_berlin/berlin.osm") 20 | 21 | map_builder = MapBuilder( 22 | net_file=net_file, 23 | poly_file=poly_file, 24 | osm_file=osm_file 25 | ) 26 | map_infos = map_builder.get_objects_infos() 27 | logger.info(f'SIM: \n{dict_to_str(map_infos)}') -------------------------------------------------------------------------------- /examples/map/plot_net.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-12 12:51:49 4 | @Description: 绘制 net 路网 5 | @LastEditTime: 2023-11-12 14:03:00 6 | ''' 7 | import sumolib 8 | import matplotlib.pyplot as plt 9 | from matplotlib.collections import LineCollection 10 | 11 | from tshub.utils.get_abs_path import get_abs_path 12 | path_convert = get_abs_path(__file__) 13 | 14 | 15 | def plotNet(net): 16 | net = sumolib.net.readNet(net) 17 | shapes = [] # shape 的坐标 18 | c = [] # 每一个 shape 的颜色 19 | w = 1 # 每一个 shape 的宽度 20 | ls = [] # shape 的样式 21 | 22 | # 绘制 lane 23 | for e in net._edges: # 获得所有的 edge 24 | for _lane in e._lanes: # 获取每一个 edge 所有的 lane 25 | shapes.append(sumolib.geomhelper.line2boundary(_lane.getShape(), _lane.getWidth())) # 获得每一个 lane 的 shape 26 | c.append('gray') 27 | ls.append('-') 28 | # sumolib.geomhelper.line2boundary(_lane.getShape(), _lane.getWidth()) 29 | 30 | # 绘制 node 31 | for _node in net.getNodes(): 32 | print(_node.getType()) 33 | if _node.getType() != 'dead_end': # 这里看一下还有哪些 type 34 | _shape = _node.getShape() 35 | shapes.append(_shape+[_shape[0]]) # 确保首尾相连 36 | c.append('b') 37 | ls.append('--') 38 | 39 | line_segments = LineCollection(shapes, linewidths=w, colors=c, linestyles=ls) 40 | ax = plt.gca() 41 | ax.add_collection(line_segments) 42 | ax.set_xmargin(0.1) 43 | ax.set_ymargin(0.1) 44 | ax.autoscale_view(True, True, True) 45 | plt.show() 46 | 47 | if __name__ == '__main__': 48 | net_file = path_convert("../sumo_env/osm_berlin/env/berlin.net.xml") 49 | plotNet(net=net_file) -------------------------------------------------------------------------------- /examples/person/get_person_state.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-24 16:06:00 4 | @Description: 查看行人的 state 5 | @LastEditTime: 2023-11-24 17:35:53 6 | ''' 7 | import sumolib 8 | from loguru import logger 9 | 10 | from tshub.utils.get_abs_path import get_abs_path 11 | from tshub.utils.init_log import set_logger 12 | from tshub.utils.format_dict import dict_to_str 13 | from tshub.person.person_builder import PersonBuilder 14 | 15 | import traci 16 | sumoBinary = sumolib.checkBinary('sumo-gui') 17 | 18 | path_convert = get_abs_path(__file__) 19 | set_logger(path_convert('./')) 20 | 21 | sumocfg_file = path_convert("../sumo_env/pedestrian_cross/env/pedestrian_cross.sumocfg") 22 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 23 | conn = traci.getConnection('0') 24 | 25 | scene_people = PersonBuilder(sumo=conn) 26 | while conn.simulation.getMinExpectedNumber() > 0: 27 | data = scene_people.get_objects_infos() # 获得行人的信息 28 | logger.info(f'SIM: {dict_to_str(data)}') 29 | 30 | conn.simulationStep() 31 | 32 | conn.close() -------------------------------------------------------------------------------- /examples/sumo_env/ego_crash/ego_crash_car_following/env.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/sumo_env/ego_crash/ego_crash_intersection/add/tls_programs.add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/sumo_env/ego_crash/ego_crash_intersection/add/tls_state.add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/sumo_env/ego_crash/ego_crash_intersection/add/tls_switch_states.add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/sumo_env/ego_crash/ego_crash_intersection/add/tls_switches.add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/sumo_env/ego_crash/ego_crash_intersection/env.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/sumo_env/ego_crash/ego_crash_intersection/inter.rou.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/sumo_env/ego_crash/ego_crash_lane_change/bottleneck.rou.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/sumo_env/ego_crash/ego_crash_lane_change/scenario.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /examples/sumo_env/osm_berlin/env/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/sumo_env/osm_berlin/env/background.png -------------------------------------------------------------------------------- /examples/sumo_env/osm_berlin/env/berlin.polygcfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/sumo_env/osm_berlin/env/berlin.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/sumo_env/osm_berlin/env/viewsettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/sumo_env/osm_berlin/script/generate_routes.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-25 18:02:47 4 | @Description: 5 | @LastEditTime: 2023-09-25 19:37:57 6 | ''' 7 | ''' 8 | @Author: WANG Maonan 9 | @Date: 2023-09-01 13:45:26 10 | @Description: 给场景生成路网 11 | @LastEditTime: 2023-09-01 14:32:04 12 | ''' 13 | from tshub.utils.get_abs_path import get_abs_path 14 | from tshub.utils.init_log import set_logger 15 | from tshub.sumo_tools.generate_routes import generate_route 16 | 17 | # 初始化日志 18 | current_file_path = get_abs_path(__file__) 19 | set_logger(current_file_path('./')) 20 | 21 | # 开启仿真 --> 指定 net 文件 22 | sumo_net = current_file_path("../env/berlin.net.xml") 23 | 24 | # 指定要生成的路口 id 和探测器保存的位置 25 | generate_route( 26 | sumo_net=sumo_net, 27 | interval=[5,5,5], 28 | edge_flow_per_minute={ 29 | '65040946#0': [8, 8, 8], 30 | '24242838#0': [8, 8, 8], 31 | '1152723807': [7, 7, 7], 32 | '-32938173#2': [7, 7, 7], 33 | '-1147648945#1': [10, 10, 13], 34 | '-1152723815': [10, 10, 7], 35 | '-1105574288#1': [10, 10, 9], 36 | '-23755718#2': [10, 10, 7] 37 | }, # 每分钟每个 edge 有多少车 38 | edge_turndef={ 39 | '24242838#0__24242838#5': [0.7, 0.7, 0.8], 40 | '24242838#5__1105574288#0': [0.9, 0.9, 0.9], 41 | }, 42 | veh_type={ 43 | 'ego': {'color':'26, 188, 156', 'probability':0.3}, 44 | 'background': {'color':'155, 89, 182', 'speed':15, 'probability':0.7}, 45 | }, 46 | output_trip=current_file_path('./testflow.trip.xml'), 47 | output_turndef=current_file_path('./testflow.turndefs.xml'), 48 | output_route=current_file_path('../env/berlin.rou.xml'), 49 | interpolate_flow=False, 50 | interpolate_turndef=False, 51 | ) -------------------------------------------------------------------------------- /examples/sumo_env/osm_berlin/script/generate_tls_additions.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-25 18:03:05 4 | @Description: 为 berlin.net.xml 生成 Traffic Light 的 add 文件 5 | @LastEditTime: 2023-09-25 18:03:28 6 | ''' 7 | from tshub.sumo_tools.additional_files.traffic_light_additions import generate_traffic_lights_additions 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.utils.init_log import set_logger 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./')) 14 | 15 | # 指定 net 文件 16 | sumo_net = current_file_path("../env/berlin.net.xml") 17 | 18 | generate_traffic_lights_additions( 19 | network_file=sumo_net, 20 | output_file=current_file_path('../add/tls.add.xml') 21 | ) -------------------------------------------------------------------------------- /examples/sumo_env/osm_berlin/script/generate_tls_detectors.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2021-11-18 12:56:54 4 | @Description: 在 berlin.net.xml, 生成探测器 5 | @LastEditTime: 2023-09-25 19:15:25 6 | ''' 7 | import libsumo as traci 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.utils.init_log import set_logger 10 | from tshub.sumo_tools.generate_detectors import generate_detector 11 | 12 | # 初始化日志 13 | current_file_path = get_abs_path(__file__) 14 | set_logger(current_file_path('./')) 15 | 16 | # 开启仿真 --> 指定 net 文件 17 | netfile_path = current_file_path("../env/berlin.net.xml") 18 | traci.start(["sumo", "-n", netfile_path]) 19 | 20 | # 指定要生成的路口 id 和探测器保存的位置 21 | g_detectors = generate_detector(traci) 22 | g_detectors.generate_multiple_detectors( 23 | tls_list=['25663405', '25663436', '25663407', '25663429', '25663423', '25663426'], 24 | result_folder=current_file_path("../add"), 25 | detectors_dict={'e2':{'detector_length':50}} 26 | ) -------------------------------------------------------------------------------- /examples/sumo_env/pedestrian_cross/add/tls.add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/sumo_env/pedestrian_cross/env/pedestrian_cross.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/sumo_env/single_junction/add/tls.add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/sumo_env/single_junction/env/single_junction.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/sumo_env/single_junction/generate_routes.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-01 13:45:26 4 | @Description: 给场景生成路网 (180s) 5 | @LastEditTime: 2024-07-21 04:30:02 6 | ''' 7 | from tshub.utils.get_abs_path import get_abs_path 8 | from tshub.utils.init_log import set_logger 9 | from tshub.sumo_tools.generate_routes import generate_route 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./'), file_log_level='WARNING', terminal_log_level='INFO') 14 | 15 | # 开启仿真 --> 指定 net 文件 16 | sumo_net = current_file_path("./env/single_junction.net.xml") 17 | 18 | # 指定要生成的路口 id 和探测器保存的位置 19 | generate_route( 20 | sumo_net=sumo_net, 21 | interval=[1,1,1], 22 | edge_flow_per_minute={ 23 | 'gsndj_n7': [15, 15, 15], 24 | '29257863#2': [15, 15, 15], 25 | 'gsndj_s4': [7, 7, 7], 26 | '161701303#7.248': [7, 7, 7], 27 | }, # 每分钟每个 edge 有多少车 28 | edge_turndef={}, 29 | veh_type={ 30 | 'ego': {'color':'26, 188, 156', 'accel':1, 'decel':1, 'probability':0.07}, 31 | 'background': {'color':'155, 89, 182', 'speed':15, 'probability':0.93}, 32 | }, 33 | output_trip=current_file_path('./testflow.trip.xml'), 34 | output_turndef=current_file_path('./testflow.turndefs.xml'), 35 | output_route=current_file_path('./testflow.rou.xml'), 36 | interpolate_flow=False, 37 | interpolate_turndef=False, 38 | ) -------------------------------------------------------------------------------- /examples/sumo_env/three_junctions/add/tls.add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/sumo_env/three_junctions/env/3junctions.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/sumo_tools/additional_file/tls_additions.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-01 15:42:25 4 | @Description: 生成 Traffic Light 的 add 文件 5 | @LastEditTime: 2023-09-01 15:52:52 6 | ''' 7 | from tshub.sumo_tools.additional_files.traffic_light_additions import generate_traffic_lights_additions 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.utils.init_log import set_logger 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./')) 14 | 15 | # 指定 net 文件 16 | sumo_net = current_file_path("../../sumo_env/three_junctions/env/3junctions.net.xml") 17 | 18 | generate_traffic_lights_additions( 19 | network_file=sumo_net, 20 | output_file=current_file_path('./tls.add.xml') 21 | ) -------------------------------------------------------------------------------- /examples/sumo_tools/analysis_output/analysis_tls_program.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-05-05 23:16:45 4 | @Description: 分析 tls program 文件, 可视化部分见 analysis_tls_program_visualization.py 文件 5 | @LastEditTime: 2024-06-25 23:44:19 6 | ''' 7 | from tshub.utils.init_log import set_logger 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.sumo_tools.analysis_output.tls_program_analysis import TLSProgramAnalysis 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./'), file_log_level="INFO") 14 | 15 | # 初始化 TLSProgramAnalysis 16 | tls_program_file = current_file_path('./output/add/tls_program.out.xml') 17 | tls_analysis = TLSProgramAnalysis(tls_program_file) 18 | 19 | # 获得每个周期内, 每个相位的持续时间 -> 可以利用这个数据进一步处理 20 | print(tls_analysis.cycle_durations) # 每个周期每个相位的持续时间 21 | print(tls_analysis.percentage_cycles) # 持续时间占比 22 | print(tls_analysis.pattern_states) # 获得周期内 state 的顺序 -------------------------------------------------------------------------------- /examples/sumo_tools/analysis_output/analysis_tls_program_visualization.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-06-25 22:57:05 4 | @Description: 对 Traffic Phase Visualization (所有相位绘制在一起) 5 | @LastEditTime: 2024-06-25 23:41:13 6 | ''' 7 | from tshub.utils.init_log import set_logger 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.sumo_tools.analysis_output.tls_program_visualization import TLSProgram_PDVis 10 | 11 | current_file_path = get_abs_path(__file__) 12 | set_logger(current_file_path('./'), file_log_level="INFO") 13 | 14 | # 初始化 TLSProgramAnalysis 15 | tls_program_file = current_file_path('./output/add/tls_program.out.xml') 16 | tls_analysis = TLSProgram_PDVis(tls_program_file) 17 | 18 | # 将所有的 Traffic Phase 绘制在一起 19 | directions_state = [ 20 | 'grrrrrgGGGrgrrrgGGr', 21 | 'GrrrrrGrrrGGrrrGrrG', 22 | 'GGGGrrGrrrrGGGrGrrr', 23 | 'GrrrGGGrrrrGrrGGrrr' 24 | ] 25 | tls_analysis.plot_allphase_ratio( 26 | directions_state, traffic_light_duration=120, 27 | image_path=current_file_path(f"./all_phase_duration.pdf") 28 | ) 29 | 30 | # 绘制指定的 Traffic Phase Duration (使用折线图) 31 | directions_state = [ 32 | 'grrrrrgGGGrgrrrgGGr', 33 | 'GGGGrrGrrrrGGGrGrrr', 34 | ] 35 | tls_analysis.plot_phase_ratio_line( 36 | phase_strs=directions_state, 37 | phase_label=['NS-SN', 'WE-EW'], 38 | fig_text='Phase Duration for Mehtod A', 39 | image_path=current_file_path(f"./phase_duration_line.pdf") 40 | ) -------------------------------------------------------------------------------- /examples/sumo_tools/analysis_output/analysis_tripinfo.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-06-25 22:07:05 4 | @Description: 分析 TripInfo 文件 5 | @LastEditTime: 2024-06-25 22:09:24 6 | ''' 7 | from tshub.utils.init_log import set_logger 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.sumo_tools.analysis_output.tripinfo_analysis import TripInfoAnalysis 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./'), file_log_level="INFO") 14 | 15 | tripinfo_file = current_file_path("./output/tripinfo.out.xml") 16 | tripinfo_parser = TripInfoAnalysis(tripinfo_file) 17 | stats = tripinfo_parser.get_all_stats() 18 | tripinfo_parser.print_stats() -------------------------------------------------------------------------------- /examples/sumo_tools/generate_pedestrian_route.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-23 22:56:22 4 | @Description: 同时生成行人和车辆的 route 5 | @LastEditTime: 2023-11-23 23:16:24 6 | ''' 7 | from tshub.utils.get_abs_path import get_abs_path 8 | from tshub.utils.init_log import set_logger 9 | from tshub.sumo_tools.generate_routes import generate_route 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./')) 14 | 15 | # 开启仿真 --> 指定 net 文件 16 | sumo_net = current_file_path("../sumo_env/pedestrian_cross/env/pedestrian_cross.net.xml") 17 | 18 | # 指定要生成的路口 id 和探测器保存的位置 19 | generate_route( 20 | sumo_net=sumo_net, 21 | interval=[5,10,15], 22 | edge_flow_per_minute={ 23 | 'E1': [15, 15, 15], 24 | '-E4': [15, 15, 15], 25 | '-E2': [7, 7, 7], 26 | 'E3': [7, 7, 7], 27 | }, # 每分钟每个 edge 有多少车 28 | edge_turndef={ 29 | '-E4__-E3': [0.7, 0.7, 0.8], 30 | }, 31 | veh_type={ 32 | 'ego': {'color':'26, 188, 156', 'probability':0.3, 'length':4.5}, 33 | 'background': {'color':'155, 89, 182', 'speed':15, 'probability':0.7, 'length':4.5}, 34 | }, 35 | walk_flow_per_minute={ 36 | 'E1__E2': [20, 30, 50], 37 | 'E1__E4': [20, 30, 50], 38 | 'E1__-E3': [20, 30, 50] 39 | }, 40 | walkfactor=0.5, 41 | output_trip=current_file_path('./_testflow.trip.xml'), 42 | output_turndef=current_file_path('./_testflow.turndefs.xml'), 43 | person_trip_file=current_file_path('./_pedestrian.trip.xml'), 44 | output_route=current_file_path('./vehicle.rou.xml'), 45 | output_person_file=current_file_path('./pedestrian.rou.xml'), 46 | interpolate_flow=False, 47 | interpolate_turndef=False, 48 | interpolate_walkflow=False 49 | ) -------------------------------------------------------------------------------- /examples/sumo_tools/generate_route/trip.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 17:42:33 4 | @Description: 测试生成 .trip.xml 文件 5 | @LastEditTime: 2023-09-01 13:49:17 6 | ''' 7 | from tshub.utils.init_log import set_logger 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.sumo_tools.generate_route.generate_trip import GenerateTrip 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./')) 14 | 15 | # 初始化参数 16 | intervals = [5,10,15] # 每个阶段的持续时间 17 | edge_flow_per_minute = { 18 | 'edge_1': [10,5,7], 19 | 'edge_2': [21,15,2], 20 | 'edge_3': [2,12,3], 21 | } # 每个阶段每分钟的车辆 22 | veh_type = { 23 | 'ego': {'color':'26, 188, 156', 'probability':0.3}, 24 | 'background': {'color':'155, 89, 182', 'probability':0.7}, 25 | } # 车辆的类型 26 | output_file = current_file_path('./test.trip.xml') 27 | 28 | # 生成 trip 文件 29 | g_trip = GenerateTrip( 30 | intervals=intervals, 31 | edge_flow_per_minute=edge_flow_per_minute, 32 | veh_type=veh_type, 33 | output_file=output_file 34 | ) 35 | g_trip.generate_trip_xml() 36 | g_trip.edit_trip_xml() -------------------------------------------------------------------------------- /examples/sumo_tools/generate_route/turn_def.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 20:05:01 4 | @Description: 生成转向概率 5 | @LastEditTime: 2023-09-01 13:53:52 6 | ''' 7 | from tshub.utils.init_log import set_logger 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.sumo_tools.generate_route.generate_turn_def import GenerateTurnDef 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./')) 14 | 15 | # 初始化参数 16 | intervals = [5,10,15] # 每个阶段的持续时间 17 | edge_turndef = { 18 | '-E9__E4': [0.7, 0.7, 0.8], 19 | '-E9__-E0': [0.1, 0.1, 0.1], 20 | } # 每个阶段每分钟的车辆 21 | sumo_net = current_file_path("../../sumo_env/three_junctions/env/3junctions.net.xml") 22 | output_file = current_file_path('./test.trundefs.xml') 23 | 24 | # 生成 trip 文件 25 | g_turndefs = GenerateTurnDef( 26 | intervals=intervals, 27 | edge_turndef=edge_turndef, 28 | sumo_net=sumo_net, 29 | output_file=output_file 30 | ) 31 | g_turndefs.generate_turn_definition() 32 | g_turndefs.edit_turn_definition() -------------------------------------------------------------------------------- /examples/sumo_tools/generate_routes.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-01 13:45:26 4 | @Description: 给场景生成路网 5 | @LastEditTime: 2024-04-08 16:56:27 6 | ''' 7 | from tshub.utils.get_abs_path import get_abs_path 8 | from tshub.utils.init_log import set_logger 9 | from tshub.sumo_tools.generate_routes import generate_route 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./'), file_log_level='WARNING', terminal_log_level='INFO') 14 | 15 | # 开启仿真 --> 指定 net 文件 16 | sumo_net = current_file_path("../sumo_env/three_junctions/env/3junctions.net.xml") 17 | 18 | # 指定要生成的路口 id 和探测器保存的位置 19 | generate_route( 20 | sumo_net=sumo_net, 21 | interval=[5,10,15], 22 | edge_flow_per_minute={ 23 | 'E0': [15, 15, 15], 24 | '-E3': [15, 15, 15], 25 | '-E9': [7, 7, 7], 26 | '-E4': [7, 7, 7], 27 | '-E5': [3, 3, 3], 28 | '-E8': [3, 3, 3], 29 | '-E6': [3, 3, 3], 30 | '-E7': [3, 3, 3] 31 | }, # 每分钟每个 edge 有多少车 32 | edge_turndef={ 33 | '-E9__E4': [0.7, 0.7, 1], 34 | '-E9__-E0': [0.1, 0.1, 0], 35 | }, 36 | veh_type={ 37 | 'ego': {'color':'26, 188, 156', 'accel':1, 'decel':1, 'probability':0.3}, 38 | 'background': {'color':'155, 89, 182', 'speed':15, 'probability':0.7}, 39 | }, 40 | output_trip=current_file_path('./testflow.trip.xml'), 41 | output_turndef=current_file_path('./testflow.turndefs.xml'), 42 | output_route=current_file_path('./testflow.rou.xml'), 43 | interpolate_flow=False, 44 | interpolate_turndef=False, 45 | ) -------------------------------------------------------------------------------- /examples/sumo_tools/generate_routes_fromOD.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Author: Maonan Wang 3 | Date: 2024-09-16 14:56:35 4 | LastEditTime: 2024-09-17 10:13:27 5 | LastEditors: Maonan Wang 6 | Description: 根据起点终点生成 route 7 | FilePath: /TransSimHub/examples/sumo_tools/generate_routes_fromOD.py 8 | ''' 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.init_log import set_logger 11 | from tshub.sumo_tools.generate_routes_fromOD import generate_route_fromOD 12 | 13 | # 初始化日志 14 | current_file_path = get_abs_path(__file__) 15 | set_logger(current_file_path('./'), file_log_level='WARNING', terminal_log_level='INFO') 16 | 17 | # 开启仿真 --> 指定 net 文件 18 | sumo_net = current_file_path("../sumo_env/three_junctions/env/3junctions.net.xml") 19 | 20 | # 指定要生成的路口 id 和探测器保存的位置 21 | generate_route_fromOD( 22 | sumo_net=sumo_net, 23 | interval=[5,10,15], 24 | od_flow_per_minute={ 25 | ('E0', 'E3'): [15, 15, 15], # (start, end) 26 | ('-E3', '-E0'): [15, 15, 15], 27 | }, # 每分钟每个 edge 有多少车 28 | veh_type={ 29 | 'ego': {'color':'26, 188, 156', 'accel':1, 'decel':1, 'probability':0.3}, 30 | 'background': {'color':'155, 89, 182', 'speed':15, 'probability':0.7}, 31 | }, 32 | output_trip=current_file_path('./testflow.trip.xml'), 33 | output_route=current_file_path('./testflow.rou.xml'), 34 | interpolate_flow=False, 35 | ) -------------------------------------------------------------------------------- /examples/sumo_tools/generate_tls_detectors.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2021-11-18 12:56:54 4 | @Description: 测试在指定路网和 tls_id, 生成探测器 5 | @LastEditTime: 2023-08-24 17:52:54 6 | ''' 7 | import libsumo as traci 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.utils.init_log import set_logger 10 | from tshub.sumo_tools.generate_detectors import generate_detector 11 | 12 | # 初始化日志 13 | current_file_path = get_abs_path(__file__) 14 | set_logger(current_file_path('./')) 15 | 16 | # 开启仿真 --> 指定 net 文件 17 | netfile_path = current_file_path("../sumo_env/three_junctions/env/3junctions.net.xml") 18 | traci.start(["sumo", "-n", netfile_path]) 19 | 20 | # 指定要生成的路口 id 和探测器保存的位置 21 | g_detectors = generate_detector(traci) 22 | g_detectors.generate_multiple_detectors( 23 | tls_list=['J1','J2','J3'], 24 | result_folder=current_file_path("../sumo_env/three_junctions/detectors"), 25 | detectors_dict={'e1':dict(), 'e1_internal':dict(), 'e2':{'detector_length':30}, 'e3':dict()} 26 | ) -------------------------------------------------------------------------------- /examples/sumo_tools/interpolation/flow.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 15:43:39 4 | @Description: 对 flow 进行插值 5 | @LastEditTime: 2023-09-01 14:11:45 6 | ''' 7 | from tshub.sumo_tools.interpolation.values_interpolation import InterpolationValues 8 | from tshub.sumo_tools.interpolation.visualize_interpolations import visualize_interpolations 9 | 10 | flow = [10,20,30,20,10] # 每个时间段的车流量, 每分钟多少车 11 | period = [5,5,5,5,5] # 每个时间段的持续时间 12 | smooth_flow = InterpolationValues(values=flow, intervals=period) 13 | 14 | # test get_smooth_turndef 15 | smooth_flow_list = smooth_flow.get_smooth_values() 16 | print(smooth_flow_list) 17 | 18 | # visualize 19 | visualize_interpolations(values=flow, period=period, smooth_values=smooth_flow_list) -------------------------------------------------------------------------------- /examples/sumo_tools/interpolation/turn_prob.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 15:43:07 4 | @Description: 对转向概率进行插值, 对插值前后的结果进行可视化 5 | @LastEditTime: 2023-09-01 14:12:23 6 | ''' 7 | from tshub.sumo_tools.interpolation.values_interpolation import InterpolationValues 8 | from tshub.sumo_tools.interpolation.visualize_interpolations import visualize_interpolations 9 | 10 | turn_def = [0.25, 0.5, 0.4, 0.7, 0.4, 0.5] # 每个时间段的转向比 11 | period = [10, 10, 10, 15, 10, 15] # 每个时间段的持续时间 12 | smooth_turn_def = InterpolationValues(values=turn_def, intervals=period) 13 | 14 | # test _interpolation 15 | print(smooth_turn_def._interpolation(15)) 16 | print(smooth_turn_def._interpolation(30)) 17 | 18 | # test get_smooth_turndef 19 | smooth_turndef_list = smooth_turn_def.get_smooth_values() 20 | print(smooth_turndef_list) 21 | 22 | # visualize 23 | visualize_interpolations(values=turn_def, period=period, smooth_values=smooth_turndef_list) -------------------------------------------------------------------------------- /examples/sumo_tools/osm_build.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-25 15:15:19 4 | @Description: 测试 osm_build 的功能, 快速从 OSM 中创建场景 5 | @LastEditTime: 2023-11-23 23:27:32 6 | ''' 7 | from tshub.utils.get_abs_path import get_abs_path 8 | from tshub.utils.init_log import set_logger 9 | from tshub.sumo_tools.osm_build import scenario_build 10 | 11 | current_file_path = get_abs_path(__file__) 12 | set_logger(current_file_path('./')) 13 | 14 | 15 | if __name__ == '__main__': 16 | osm_file = current_file_path("../sumo_env/osm_berlin/berlin.osm") 17 | output_directory = current_file_path("../sumo_env/osm_berlin/env/") 18 | scenario_build( 19 | osm_file=osm_file, 20 | output_directory=output_directory 21 | ) -------------------------------------------------------------------------------- /examples/sumo_tools/osm_filter.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-05-27 13:14:57 4 | @Description: Convert OSM to Net 5 | @LastEditTime: 2024-05-27 16:16:34 6 | ''' 7 | import os 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.utils.init_log import set_logger 10 | from tshub.sumo_tools.osm_build import scenario_build # osm -> net.xml & poly.xml 11 | from tshub.sumo_tools.osm_filter import extract_ids, filter_osm # net.xml & poly.xml -> osm 12 | 13 | current_file_path = get_abs_path(__file__) 14 | set_logger(current_file_path('./')) 15 | 16 | 17 | if __name__ == '__main__': 18 | osm_file = current_file_path("../sumo_env/osm_berlin/berlin.osm") 19 | output_directory = current_file_path("../sumo_env/osm_berlin/env/") 20 | scenario_build( 21 | osm_file=osm_file, 22 | output_directory=output_directory 23 | ) 24 | 25 | keep_ids = extract_ids( 26 | poly_xml_path=os.path.join(output_directory, 'berlin.poly.xml'), 27 | net_xml_path=os.path.join(output_directory, 'berlin.net.xml'), 28 | ) 29 | filter_osm( 30 | ways_to_keep=keep_ids, 31 | input_osm=osm_file, 32 | output_osm=current_file_path("./berlin_filter.osm") 33 | ) -------------------------------------------------------------------------------- /examples/sumo_tools/sumo_infos/get_edge_info.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 19:34:43 4 | @Description: 获得 edge in 和 out 的信息 5 | @LastEditTime: 2023-08-31 19:39:51 6 | ''' 7 | import sumolib 8 | from loguru import logger 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.format_dict import dict_to_str 11 | from tshub.sumo_tools.sumo_infos.edge_info import get_in_outgoing 12 | 13 | current_file_path = get_abs_path(__file__) 14 | 15 | sumo_net = current_file_path("../../sumo_env/three_junctions/env/3junctions.net.xml") 16 | net = sumolib.net.readNet(sumo_net) # 读取 sumo net 17 | 18 | edge_info = get_in_outgoing(net=net, edge_id='-E9') 19 | logger.info(f'SIM: \n{dict_to_str(edge_info)}.') -------------------------------------------------------------------------------- /examples/sumo_tools/sumo_infos/get_tls_connections.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-24 17:16:06 4 | @Description: 获得多个路口, 每一个路口的所有的 connection 5 | @LastEditTime: 2023-08-24 17:36:33 6 | ''' 7 | from loguru import logger 8 | import libsumo as traci 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.format_dict import dict_to_str 11 | from tshub.sumo_tools.sumo_infos.tls_connections import tls_connection 12 | 13 | current_file_path = get_abs_path(__file__) 14 | 15 | # 开启环境 16 | traci.start(["sumo", "-c", current_file_path("../../sumo_env/three_junctions/env/3junctions.sumocfg")]) 17 | conn = traci 18 | 19 | # 打印对应 traffic junction 的 id 的信息 20 | junctions = ['J1','J2','J3'] 21 | junctions_info = tls_connection(conn) 22 | results = junctions_info.get_tls_connections(junctions) 23 | json_str = dict_to_str(results) # dict -> str 24 | logger.info(json_str) -------------------------------------------------------------------------------- /examples/traffic_light/get_tls_state.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-25 13:28:22 4 | @Description: 获得 Traffic Light Signal State 5 | @LastEditTime: 2023-08-30 16:23:38 6 | ''' 7 | import sumolib 8 | from loguru import logger 9 | 10 | from tshub.traffic_light.traffic_light_builder import TrafficLightBuilder 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.utils.init_log import set_logger 13 | from tshub.utils.format_dict import dict_to_str 14 | 15 | import traci 16 | sumoBinary = sumolib.checkBinary('sumo-gui') 17 | 18 | path_convert = get_abs_path(__file__) 19 | set_logger(path_convert('./')) 20 | 21 | sumocfg_file = path_convert("../sumo_env/single_junction/env/single_junction.sumocfg") 22 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 23 | conn = traci.getConnection('0') 24 | 25 | # 两种动作设计, 分别是 choose_next_phase 和 next_or_not 26 | scene_traffic_lights = TrafficLightBuilder(sumo=conn, tls_ids=['htddj_gsndj'], action_type='next_or_not') 27 | while conn.simulation.getMinExpectedNumber() > 0: 28 | tls_infos = scene_traffic_lights.get_objects_infos() 29 | logger.info(f'SIM: \n{dict_to_str(tls_infos)}') 30 | 31 | conn.simulationStep() # 仿真到某一步 32 | 33 | conn.close() -------------------------------------------------------------------------------- /examples/traffic_light/traffic_light_action/tls_adjustCycleDuration.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-05-01 15:34:53 4 | @Description: 每个周期内对所有的相位持续时间进行调整 5 | @LastEditTime: 2024-05-01 15:59:36 6 | ''' 7 | import sumolib 8 | import numpy as np 9 | from loguru import logger 10 | 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.utils.init_log import set_logger 13 | from tshub.utils.format_dict import dict_to_str 14 | 15 | from tshub.traffic_light.traffic_light_builder import TrafficLightBuilder 16 | 17 | import traci 18 | sumoBinary = sumolib.checkBinary('sumo-gui') 19 | 20 | path_convert = get_abs_path(__file__) 21 | set_logger(path_convert('./')) 22 | 23 | sumocfg_file = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 24 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 25 | conn = traci.getConnection('0') 26 | 27 | action_index = 0 # 动作的 id 28 | scene_traffic_lights = TrafficLightBuilder(sumo=conn, tls_ids=['htddj_gsndj'], action_type='adjust_cycle_duration') 29 | while conn.simulation.getMinExpectedNumber() > 0: 30 | # 获得路口信息 31 | tls_infos = scene_traffic_lights.get_objects_infos() # 返回路口信息 32 | logger.info(f'SIM: \n{dict_to_str(tls_infos)}') 33 | 34 | # 控制路口信息 35 | if tls_infos['htddj_gsndj']['can_perform_action']: 36 | # 每个相位时间随机增加或者减少 37 | scene_traffic_lights.control_objects({'htddj_gsndj':[np.random.choice([-5,0,5]) for _ in range(4)]}) 38 | else: # 此时下发的动作会无效 39 | scene_traffic_lights.control_objects({'htddj_gsndj':None}) 40 | 41 | conn.simulationStep() # 仿真到某一步 42 | 43 | conn.close() -------------------------------------------------------------------------------- /examples/traffic_light/traffic_light_action/tls_choosenextphase.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-25 13:28:22 4 | @Description: 控制 Traffic Light Signal, 使用 Choose Next Phase 的动作设计 5 | @LastEditTime: 2023-08-30 16:24:13 6 | ''' 7 | import sumolib 8 | from loguru import logger 9 | 10 | from tshub.traffic_light.traffic_light_builder import TrafficLightBuilder 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.utils.init_log import set_logger 13 | from tshub.utils.format_dict import dict_to_str 14 | 15 | import traci 16 | sumoBinary = sumolib.checkBinary('sumo-gui') 17 | 18 | path_convert = get_abs_path(__file__) 19 | set_logger(path_convert('./')) 20 | 21 | sumocfg_file = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 22 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 23 | conn = traci.getConnection('0') 24 | 25 | action_index = 0 # 动作的 id 26 | scene_traffic_lights = TrafficLightBuilder(sumo=conn, tls_ids=['htddj_gsndj'], action_type='choose_next_phase') 27 | while conn.simulation.getMinExpectedNumber() > 0: 28 | # 获得路口信息 29 | tls_infos = scene_traffic_lights.get_objects_infos() # 返回路口信息 30 | logger.info(f'SIM: \n{dict_to_str(tls_infos)}') 31 | 32 | # 控制路口信息 33 | if tls_infos['htddj_gsndj']['can_perform_action']: 34 | scene_traffic_lights.control_objects({'htddj_gsndj':action_index}) 35 | action_index = (action_index+1)%4 36 | logger.debug(f'SIM: Action Index: {action_index}') 37 | else: # 此时下发的动作会无效 38 | scene_traffic_lights.control_objects({'htddj_gsndj':None}) 39 | 40 | conn.simulationStep() # 仿真到某一步 41 | 42 | conn.close() -------------------------------------------------------------------------------- /examples/traffic_light/traffic_light_action/tls_choosenextphase_syn.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-25 13:28:22 4 | @Description: 控制 Traffic Light Signal (Synchronize), 使用 Choose Next Phase 的动作设计 5 | @LastEditTime: 2024-04-24 20:47:28 6 | ''' 7 | import sumolib 8 | from loguru import logger 9 | 10 | from tshub.traffic_light.traffic_light_builder import TrafficLightBuilder 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.utils.init_log import set_logger 13 | from tshub.utils.format_dict import dict_to_str 14 | 15 | import traci 16 | sumoBinary = sumolib.checkBinary('sumo-gui') 17 | 18 | path_convert = get_abs_path(__file__) 19 | set_logger(path_convert('./')) 20 | 21 | sumocfg_file = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 22 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 23 | conn = traci.getConnection('0') 24 | 25 | action_index = 0 # 动作的 id 26 | scene_traffic_lights = TrafficLightBuilder(sumo=conn, tls_ids=['htddj_gsndj'], action_type='choose_next_phase_syn') 27 | while conn.simulation.getMinExpectedNumber() > 0: 28 | # 获得路口信息 29 | tls_infos = scene_traffic_lights.get_objects_infos() # 返回路口信息 30 | logger.info(f'SIM: \n{dict_to_str(tls_infos)}') 31 | 32 | # 控制路口信息 33 | if tls_infos['htddj_gsndj']['can_perform_action']: 34 | scene_traffic_lights.control_objects({'htddj_gsndj':action_index}) 35 | action_index = (action_index+1)%4 36 | logger.debug(f'SIM: Action Index: {action_index}') 37 | else: # 此时下发的动作会无效 38 | scene_traffic_lights.control_objects({'htddj_gsndj':None}) 39 | 40 | conn.simulationStep() # 仿真到某一步 41 | 42 | conn.close() -------------------------------------------------------------------------------- /examples/traffic_light/traffic_light_action/tls_nextornot.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-25 13:28:22 4 | @Description: 控制 Traffic Light Signal, 使用 Next or Not 的动作设计 5 | @LastEditTime: 2023-08-30 16:24:07 6 | ''' 7 | import sumolib 8 | from loguru import logger 9 | 10 | from tshub.traffic_light.traffic_light_builder import TrafficLightBuilder 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.utils.init_log import set_logger 13 | from tshub.utils.format_dict import dict_to_str 14 | 15 | import traci 16 | sumoBinary = sumolib.checkBinary('sumo-gui') 17 | 18 | path_convert = get_abs_path(__file__) 19 | set_logger(path_convert('./')) 20 | 21 | sumocfg_file = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 22 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 23 | conn = traci.getConnection('0') 24 | 25 | # 两种动作设计, 分别是 choose_next_phase 和 next_or_not 26 | action_index = 0 # 动作的 id 27 | scene_traffic_lights = TrafficLightBuilder(sumo=conn, tls_ids=['htddj_gsndj'], action_type='next_or_not') 28 | while conn.simulation.getMinExpectedNumber() > 0: 29 | # 获得路口信息 30 | tls_infos = scene_traffic_lights.get_objects_infos() # 返回路口信息 31 | logger.info(f'SIM: \n{dict_to_str(tls_infos)}') 32 | 33 | # 控制路口信息 34 | if tls_infos['htddj_gsndj']['can_perform_action']: 35 | scene_traffic_lights.control_objects({'htddj_gsndj':action_index}) 36 | action_index = (action_index+1)%2 37 | else: # 此时下发的动作会无效 38 | scene_traffic_lights.control_objects({'htddj_gsndj':None}) 39 | 40 | conn.simulationStep() # 仿真到某一步 41 | 42 | conn.close() -------------------------------------------------------------------------------- /examples/traffic_light/traffic_light_action/tls_setPhaseDuration.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-06-27 19:05:17 4 | @Description: 每次调整单个相位的持续时间 5 | @LastEditTime: 2024-06-27 19:42:29 6 | ''' 7 | import sumolib 8 | import numpy as np 9 | from loguru import logger 10 | 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.utils.init_log import set_logger 13 | from tshub.utils.format_dict import dict_to_str 14 | 15 | from tshub.traffic_light.traffic_light_builder import TrafficLightBuilder 16 | 17 | import traci 18 | sumoBinary = sumolib.checkBinary('sumo-gui') 19 | 20 | path_convert = get_abs_path(__file__) 21 | set_logger(path_convert('./')) 22 | 23 | sumocfg_file = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 24 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 25 | conn = traci.getConnection('0') 26 | 27 | action_index = 0 # 动作的 id 28 | scene_traffic_lights = TrafficLightBuilder( 29 | sumo=conn, 30 | tls_ids=['htddj_gsndj'], 31 | action_type='set_phase_diration', 32 | delta_time=None # 这里推荐设置为 None 33 | ) 34 | while conn.simulation.getMinExpectedNumber() > 0: 35 | # 获得路口信息 36 | tls_infos = scene_traffic_lights.get_objects_infos() # 返回路口信息 37 | logger.info(f'SIM: \n{dict_to_str(tls_infos)}') 38 | 39 | # 控制路口信息 40 | if tls_infos['htddj_gsndj']['can_perform_action']: 41 | # 每个相位的持续时间选择是从 10,15,20 里面选择 42 | new_phase_duration = np.random.choice([10, 15, 20]) 43 | scene_traffic_lights.control_objects({'htddj_gsndj':new_phase_duration}) 44 | else: # 此时下发的动作会无效 45 | scene_traffic_lights.control_objects({'htddj_gsndj':None}) 46 | 47 | conn.simulationStep() # 仿真到某一步 48 | 49 | conn.close() -------------------------------------------------------------------------------- /examples/tshub_dataset/osm2net.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-05-27 13:14:57 4 | @Description: Convert OSM to Net 5 | @LastEditTime: 2024-05-28 17:54:58 6 | ''' 7 | import os 8 | from tshub.utils.get_abs_path import get_abs_path 9 | from tshub.utils.init_log import set_logger 10 | from tshub.sumo_tools.osm_build import scenario_build # osm -> net.xml & poly.xml 11 | from tshub.sumo_tools.osm_filter import extract_ids, filter_osm # net.xml & poly.xml -> osm 12 | 13 | current_file_path = get_abs_path(__file__) 14 | set_logger(current_file_path('./')) 15 | 16 | 17 | if __name__ == '__main__': 18 | osm_file = current_file_path("./shanghai_songjiang.osm") 19 | output_directory = current_file_path("./shanghai_songjiang/") 20 | scenario_build( 21 | osm_file=osm_file, 22 | output_directory=output_directory 23 | ) 24 | keep_ids = extract_ids( 25 | poly_xml_path=os.path.join(output_directory, 'shanghai_songjiang.poly.xml'), 26 | net_xml_path=os.path.join(output_directory, 'shanghai_songjiang.net.xml'), 27 | ) 28 | filter_osm( 29 | ways_to_keep=keep_ids, 30 | input_osm=osm_file, 31 | output_osm=current_file_path("./shanghai_songjiang_filter.osm") 32 | ) -------------------------------------------------------------------------------- /examples/tshub_env/tshub_env_person.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-24 18:05:38 4 | @Description: 环境返回行人的信息 5 | @LastEditTime: 2023-11-24 18:27:07 6 | ''' 7 | import numpy as np 8 | from loguru import logger 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.init_log import set_logger 11 | from tshub.tshub_env.tshub_env import TshubEnvironment 12 | from tshub.utils.format_dict import dict_to_str 13 | 14 | path_convert = get_abs_path(__file__) 15 | set_logger(path_convert('./')) 16 | 17 | sumo_cfg = path_convert("../sumo_env/pedestrian_cross/env/pedestrian_cross.sumocfg") 18 | net_file = path_convert("../sumo_env/pedestrian_cross/env/pedestrian_cross.net.xml") 19 | 20 | tshub_env = TshubEnvironment( 21 | sumo_cfg=sumo_cfg, 22 | is_map_builder_initialized=True, 23 | is_aircraft_builder_initialized=False, 24 | is_vehicle_builder_initialized=True, 25 | is_traffic_light_builder_initialized=True, 26 | is_person_builder_initialized=True, 27 | # map builder 28 | net_file=net_file, 29 | # traffic light builder 30 | tls_ids=['J4'], 31 | tls_action_type='next_or_not', 32 | # vehicle builder 33 | vehicle_action_type='lane', 34 | use_gui=True, num_seconds=700 35 | ) 36 | 37 | obs = tshub_env.reset() 38 | done = False 39 | 40 | while not done: 41 | actions = { 42 | 'vehicle': dict(), 43 | } 44 | obs, reward, info, done = tshub_env.step(actions=actions) 45 | logger.info(f"SIM: {info['step_time']} \n{dict_to_str(obs)}") 46 | tshub_env._close_simulation() -------------------------------------------------------------------------------- /examples/tshub_env3d/map_model_merge/model/ground.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/map_model_merge/model/ground.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/map_model_merge/model/lane_lines.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/map_model_merge/model/lane_lines.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/map_model_merge/model/map.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/map_model_merge/model/map.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/map_model_merge/model/road_lines.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/map_model_merge/model/road_lines.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/map_model_merge/sumo/merge.rou.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/tshub_env3d/map_model_merge/sumo/merge.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/tshub_env3d/map_model_merge/sumonet_to_3d.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-03 16:34:37 4 | @Description: 将 SUMO Net 转换为 3D 的素材 5 | LastEditTime: 2025-03-28 18:45:34 6 | ''' 7 | from tshub.utils.init_log import set_logger 8 | from tshub.utils.get_abs_path import get_abs_path 9 | 10 | from tshub.tshub_env3d.vis3d_sumonet_convert.sumonet_to_tshub3d import SumoNet3D 11 | 12 | path_convert = get_abs_path(__file__) 13 | set_logger(path_convert('./'), terminal_log_level='INFO') 14 | 15 | if __name__ == '__main__': 16 | netxml = path_convert("./sumo/merge.net.xml") # 路网路径 17 | sumonet_to_3d = SumoNet3D(net_file=netxml) 18 | sumonet_to_3d.to_glb(glb_dir=path_convert(f"./model/")) -------------------------------------------------------------------------------- /examples/tshub_env3d/multi_junctions/3d_assets/ground.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/multi_junctions/3d_assets/ground.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/multi_junctions/3d_assets/lane_lines.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/multi_junctions/3d_assets/lane_lines.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/multi_junctions/3d_assets/map.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/multi_junctions/3d_assets/map.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/multi_junctions/3d_assets/road_lines.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/multi_junctions/3d_assets/road_lines.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/multi_junctions/a_sumonet_to_3d.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-03 16:34:37 4 | @Description: 将 SUMO Net 转换为 3D 的素材 (多路口) 5 | LastEditTime: 2025-04-15 15:22:55 6 | ''' 7 | from tshub.utils.init_log import set_logger 8 | from tshub.utils.get_abs_path import get_abs_path 9 | 10 | from tshub.tshub_env3d.vis3d_sumonet_convert.sumonet_to_tshub3d import SumoNet3D 11 | 12 | path_convert = get_abs_path(__file__) 13 | set_logger(path_convert('./'), terminal_log_level='INFO') 14 | 15 | if __name__ == '__main__': 16 | netxml = path_convert("./sumo_net/multi_junctions.net.xml") 17 | sumonet_to_3d = SumoNet3D(net_file=netxml) 18 | sumonet_to_3d.to_glb(glb_dir=path_convert(f"./3d_assets/")) -------------------------------------------------------------------------------- /examples/tshub_env3d/multi_junctions/sumo_net/generate_routes.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-01 13:45:26 4 | @Description: 随机生成车辆, 包含不同的车辆类型 5 | LastEditTime: 2025-04-15 15:20:04 6 | ''' 7 | from tshub.utils.get_abs_path import get_abs_path 8 | from tshub.utils.init_log import set_logger 9 | from tshub.sumo_tools.generate_routes import generate_route 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./'), file_log_level='WARNING', terminal_log_level='INFO') 14 | 15 | # 开启仿真 --> 指定 net 文件 16 | sumo_net = current_file_path("./multi_junctions.net.xml") 17 | 18 | # 指定要生成的路口 id 和探测器保存的位置 19 | generate_route( 20 | sumo_net=sumo_net, 21 | interval=[1,1,1], 22 | edge_flow_per_minute={ 23 | 'E0': [10, 10, 10], 24 | 'E1': [10, 10, 10], 25 | '-E2': [10, 10, 10], 26 | 'E5': [10, 10, 10], 27 | '-E6': [10, 10, 10], 28 | '-E8': [10, 10, 10], 29 | '-E7': [10, 10, 10], 30 | }, # 每分钟每个 edge 有多少车 31 | edge_turndef={}, 32 | veh_type={ 33 | 'background': {'color':'220,220,220', 'length': 5, 'probability':0.6}, 34 | 'police': {'color':'0,0,255', 'length': 5, 'probability':0.1}, 35 | 'emergency': {'color':'255,165,0', 'length': 6.5, 'probability':0.1}, 36 | 'fire_engine': {'color':'255,0,0', 'length': 7.1, 'probability':0.1}, 37 | 'taxi': {'color':'255,255,0', 'length': 5, 'probability':0.1}, 38 | }, 39 | output_trip=current_file_path('./testflow.trip.xml'), 40 | output_turndef=current_file_path('./testflow.turndefs.xml'), 41 | output_route=current_file_path('./multi_junctions.rou.xml'), 42 | interpolate_flow=False, 43 | interpolate_turndef=False, 44 | ) -------------------------------------------------------------------------------- /examples/tshub_env3d/multi_junctions/sumo_net/multi_junctions.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/tshub_env3d/single_junction/3d_assets/ground.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/single_junction/3d_assets/ground.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/single_junction/3d_assets/lane_lines.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/single_junction/3d_assets/lane_lines.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/single_junction/3d_assets/map.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/single_junction/3d_assets/map.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/single_junction/3d_assets/road_lines.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env3d/single_junction/3d_assets/road_lines.glb -------------------------------------------------------------------------------- /examples/tshub_env3d/single_junction/a_sumonet_to_3d.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-03 16:34:37 4 | @Description: 将 SUMO Net 转换为 3D 的素材 5 | LastEditTime: 2025-03-28 18:45:34 6 | ''' 7 | from tshub.utils.init_log import set_logger 8 | from tshub.utils.get_abs_path import get_abs_path 9 | 10 | from tshub.tshub_env3d.vis3d_sumonet_convert.sumonet_to_tshub3d import SumoNet3D 11 | 12 | path_convert = get_abs_path(__file__) 13 | set_logger(path_convert('./'), terminal_log_level='INFO') 14 | 15 | if __name__ == '__main__': 16 | netxml = path_convert("./sumo_net/single_junction.net.xml") # 路网路径 17 | sumonet_to_3d = SumoNet3D(net_file=netxml) 18 | sumonet_to_3d.to_glb(glb_dir=path_convert(f"./3d_assets/")) -------------------------------------------------------------------------------- /examples/tshub_env3d/single_junction/sumo_net/generate_routes.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-01 13:45:26 4 | @Description: 随机生成车辆, 包含不同的车辆类型 5 | LastEditTime: 2025-04-14 19:51:26 6 | ''' 7 | from tshub.utils.get_abs_path import get_abs_path 8 | from tshub.utils.init_log import set_logger 9 | from tshub.sumo_tools.generate_routes import generate_route 10 | 11 | # 初始化日志 12 | current_file_path = get_abs_path(__file__) 13 | set_logger(current_file_path('./'), file_log_level='WARNING', terminal_log_level='INFO') 14 | 15 | # 开启仿真 --> 指定 net 文件 16 | sumo_net = current_file_path("./single_junction.net.xml") 17 | 18 | # 指定要生成的路口 id 和探测器保存的位置 19 | generate_route( 20 | sumo_net=sumo_net, 21 | interval=[1,1,1], 22 | edge_flow_per_minute={ 23 | 'E2': [10, 10, 10], 24 | '-E1': [10, 10, 10], 25 | '-E3': [7, 7, 7], 26 | 'E0': [7, 7, 7], 27 | }, # 每分钟每个 edge 有多少车 28 | edge_turndef={}, 29 | veh_type={ 30 | 'background': {'color':'220,220,220', 'length': 5, 'probability':0.6}, 31 | 'police': {'color':'0,0,255', 'length': 5, 'probability':0.1}, 32 | 'emergency': {'color':'255,165,0', 'length': 6.5, 'probability':0.1}, 33 | 'fire_engine': {'color':'255,0,0', 'length': 7.1, 'probability':0.1}, 34 | 'taxi': {'color':'255,255,0', 'length': 5, 'probability':0.1}, 35 | }, 36 | output_trip=current_file_path('./testflow.trip.xml'), 37 | output_turndef=current_file_path('./testflow.turndefs.xml'), 38 | output_route=current_file_path('./single_junction.rou.xml'), 39 | interpolate_flow=False, 40 | interpolate_turndef=False, 41 | ) -------------------------------------------------------------------------------- /examples/tshub_env3d/single_junction/sumo_net/single_junction.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/tshub_env_render/assets/rgb_global.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env_render/assets/rgb_global.gif -------------------------------------------------------------------------------- /examples/tshub_env_render/assets/rgb_node.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env_render/assets/rgb_node.gif -------------------------------------------------------------------------------- /examples/tshub_env_render/assets/rgb_vehicle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env_render/assets/rgb_vehicle.gif -------------------------------------------------------------------------------- /examples/tshub_env_render/assets/sumogui_global.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env_render/assets/sumogui_global.gif -------------------------------------------------------------------------------- /examples/tshub_env_render/assets/sumogui_node.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env_render/assets/sumogui_node.gif -------------------------------------------------------------------------------- /examples/tshub_env_render/assets/sumogui_vehicle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/examples/tshub_env_render/assets/sumogui_vehicle.gif -------------------------------------------------------------------------------- /examples/utils/nested_dict_example.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-24 16:18:38 4 | @Description: 5 | @LastEditTime: 2023-08-24 16:18:39 6 | ''' 7 | from collections import defaultdict 8 | from tshub.utils.nested_dict_conversion import create_nested_defaultdict, defaultdict2dict 9 | 10 | # 测试 create_nested_defaultdict 函数 11 | nested_dict = create_nested_defaultdict() 12 | nested_dict['a']['b']['c'] = 123 13 | print(nested_dict['a']['b']['c']) # 输出: 123 14 | 15 | # 测试 defaultdict2dict 函数 16 | nested_dict = create_nested_defaultdict() 17 | nested_dict['a']['b']['c'] = 123 18 | 19 | regular_dict = defaultdict2dict(nested_dict) 20 | print(regular_dict) # 输出: {'a': {'b': {'c': 123}}} 21 | -------------------------------------------------------------------------------- /examples/utils/parse_trip_info/analysis_trip_info.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-12-01 20:14:30 4 | @Description: 分析 Trip Info 文件 5 | @LastEditTime: 2023-12-01 20:15:54 6 | ''' 7 | from tshub.utils.parse_trip_info import TripInfoStats 8 | from tshub.utils.get_abs_path import get_abs_path 9 | 10 | path_convert = get_abs_path(__file__) 11 | 12 | if __name__ == '__main__': 13 | stats = TripInfoStats(path_convert('./single_junction.tripinfo.xml')) 14 | print(stats.output_str()) 15 | stats.to_csv(path_convert('./output.csv')) -------------------------------------------------------------------------------- /examples/utils/parse_trip_info/output.csv: -------------------------------------------------------------------------------- 1 | vType,stat_name,count,min,max,median,mean,std 2 | car_2,duration,291,44.0,132.0,85.0,86.76975945017182,19.00927372550046 3 | car_2,routeLength,291,1021.63,1446.0,1432.04,1259.6446391752604,190.84964267560454 4 | car_2,speed,291,9.279478260869567,25.572142857142858,14.16732558139535,15.13455341906012,3.7575284006830434 5 | car_2,stopTime,291,0.0,0.0,0.0,0.0,0.0 6 | car_2,timeLoss,291,6.81,74.63,39.99,40.141340206185575,18.081083332934092 7 | car_2,waitingCount,291,0.0,3.0,1.0,0.8625429553264605,0.5452125857119926 8 | car_2,waitingTime,291,0.0,56.0,18.0,19.123711340206185,16.535034802402908 9 | car_1,duration,318,40.0,132.0,83.0,82.28301886792453,23.687465059590682 10 | car_1,routeLength,318,1019.63,1444.0,1065.14,1206.8944654088086,199.9407727276456 11 | car_1,speed,318,8.64093220338983,26.254545454545454,15.54391304347826,15.772481499401115,4.469235553081967 12 | car_1,stopTime,318,0.0,0.0,0.0,0.0,0.0 13 | car_1,timeLoss,318,5.87,85.31,36.41,38.03025157232706,22.19696289071844 14 | car_1,waitingCount,318,0.0,2.0,1.0,0.6855345911949685,0.5336284338443956 15 | car_1,waitingTime,318,0.0,58.0,11.0,18.79559748427673,19.697373466997018 16 | -------------------------------------------------------------------------------- /examples/utils/parse_trip_info/simulate_with_trioinfo.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-12-01 14:39:47 4 | @Description: 开启仿真同时保存 tripinfo, 只对车辆进行仿真, 同时保存 tripinfo 5 | @LastEditTime: 2023-12-01 20:13:18 6 | ''' 7 | import numpy as np 8 | from loguru import logger 9 | from tshub.utils.get_abs_path import get_abs_path 10 | from tshub.utils.init_log import set_logger 11 | from tshub.tshub_env.tshub_env import TshubEnvironment 12 | from tshub.utils.format_dict import dict_to_str 13 | 14 | path_convert = get_abs_path(__file__) 15 | set_logger(path_convert('./')) 16 | 17 | sumo_cfg = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 18 | 19 | tshub_env = TshubEnvironment( 20 | sumo_cfg=sumo_cfg, 21 | is_map_builder_initialized=False, 22 | is_aircraft_builder_initialized=False, 23 | is_vehicle_builder_initialized=True, 24 | is_traffic_light_builder_initialized=False, 25 | tls_ids=['htddj_gsndj'], 26 | vehicle_action_type='lane', 27 | tls_action_type='next_or_not', 28 | use_gui=True, 29 | num_seconds=2000, 30 | trip_info=path_convert('./single_junction.tripinfo.xml') 31 | ) 32 | 33 | obs = tshub_env.reset() 34 | done = False 35 | 36 | while not done: 37 | actions = { 38 | 'vehicle': dict(), 39 | 'tls': {'htddj_gsndj':0}, 40 | 'aircraft': { 41 | "a1": (1, np.random.randint(8)), 42 | "a2": (1, np.random.randint(8)), 43 | } 44 | } 45 | obs, reward, info, done = tshub_env.step(actions=actions) 46 | logger.info(f"SIM: {info['step_time']} \n{dict_to_str(obs)}") 47 | tshub_env._close_simulation() -------------------------------------------------------------------------------- /examples/v2x/v2x_utils/snr_to_packetloss.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-08-10 20:22:49 4 | @Description: 5 | @LastEditTime: 2024-08-10 21:04:47 6 | ''' 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | from tshub.v2x import calculate_outage_probability 10 | 11 | if __name__ == '__main__': 12 | snr_input = 10 # SNR in dB 13 | outage_prob = calculate_outage_probability(snr_input) 14 | print(f"The outage probability is {outage_prob:.4f}") 15 | 16 | # 绘制 snr 与 packet loss 的关系 17 | snr_values = np.linspace(-20, 30, 300) 18 | outage_probabilities = [calculate_outage_probability(snr) for snr in snr_values] 19 | 20 | # Plotting the outage probability against SNR 21 | plt.figure(figsize=(10, 6)) 22 | plt.plot(snr_values, outage_probabilities, label='Outage Probability') 23 | plt.xlabel('SNR (dB)') 24 | plt.ylabel('Packet Loss Probability') 25 | plt.title('Packet Loss Probability vs. SNR') 26 | plt.grid(True) 27 | plt.legend() 28 | plt.show() -------------------------------------------------------------------------------- /examples/vehicles/ego_vehicles/vehicle_ego.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-01 14:45:54 4 | @Description: 使用 Lane 来控制车辆, 只控制是 ego 类型的车 5 | @LastEditTime: 2024-08-11 19:36:55 6 | ''' 7 | import traci 8 | import sumolib 9 | import numpy as np 10 | 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.vehicle.vehicle_builder import VehicleBuilder 13 | from tshub.utils.init_log import set_logger 14 | 15 | def filter_ego_id(vehicle_data): 16 | ego_ids = [] 17 | for _veh_id, _veh_info in vehicle_data.items(): 18 | if _veh_info['vehicle_type'] == 'ego': 19 | ego_ids.append(_veh_id) 20 | return ego_ids 21 | 22 | sumoBinary = sumolib.checkBinary('sumo-gui') 23 | 24 | path_convert = get_abs_path(__file__) 25 | set_logger(path_convert('./')) 26 | 27 | sumocfg_file = path_convert("../../sumo_env/three_junctions/env/3junctions.sumocfg") 28 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 29 | conn = traci.getConnection('0') 30 | 31 | scene_vehicles = VehicleBuilder(sumo=conn, action_type='lane') 32 | while conn.simulation.getMinExpectedNumber() > 0: 33 | # 获得车辆的信息 34 | data = scene_vehicles.get_objects_infos() 35 | 36 | # 控制部分车辆, 分别是 lane_change, speed 37 | ego_vehicles = filter_ego_id(data) 38 | actions = { 39 | _veh_id:{'lane_change': np.random.randint(4)} 40 | for _veh_id in ego_vehicles 41 | } 42 | scene_vehicles.control_objects(actions) 43 | 44 | conn.simulationStep() 45 | 46 | conn.close() -------------------------------------------------------------------------------- /examples/vehicles/ego_vehicles/vehicle_laneChange_crash.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-05-05 14:50:29 4 | @Description: 控制车辆进行碰撞, 由于换道引发的碰撞 5 | @LastEditTime: 2024-08-11 19:39:46 6 | ''' 7 | import traci 8 | import sumolib 9 | import numpy as np 10 | 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.vehicle.vehicle_builder import VehicleBuilder 13 | from tshub.utils.init_log import set_logger 14 | 15 | sumoBinary = sumolib.checkBinary('sumo-gui') 16 | 17 | path_convert = get_abs_path(__file__) 18 | set_logger(path_convert('./')) 19 | 20 | sumocfg_file = path_convert("../../sumo_env/ego_crash/ego_crash_lane_change/scenario.sumocfg") 21 | traci.start([sumoBinary, "-c", sumocfg_file, "--collision.action", "remove"], label='0') # 需要加入 collision.action 22 | conn = traci.getConnection('0') 23 | 24 | scene_vehicles = VehicleBuilder(sumo=conn, action_type='lane_continuous_speed') 25 | 26 | while conn.simulation.getMinExpectedNumber() > 0: 27 | # 获得车辆的信息 28 | data = scene_vehicles.get_objects_infos() 29 | 30 | actions = {} 31 | if "1" in data: 32 | actions["1"] = {'lane_change': np.random.randint(3), 'target_speed':15} 33 | print(actions) 34 | scene_vehicles.control_objects(actions) 35 | 36 | conn.simulationStep() 37 | 38 | conn.close() -------------------------------------------------------------------------------- /examples/vehicles/ego_vehicles/vehicle_speed_crash.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-04-13 15:01:42 4 | @Description: 控制车辆进行碰撞, 由于速度引发的碰撞 5 | => ego_crash_car_following, 追尾测试 6 | => ego_crash_intersection, 无保护左转撞车测试 7 | @LastEditTime: 2024-08-11 19:40:01 8 | ''' 9 | import traci 10 | import sumolib 11 | 12 | from tshub.utils.get_abs_path import get_abs_path 13 | from tshub.vehicle.vehicle_builder import VehicleBuilder 14 | from tshub.utils.init_log import set_logger 15 | 16 | CRASH_TYPE = "ego_crash_car_following" # ego_crash_car_following, ego_crash_intersection 17 | 18 | sumoBinary = sumolib.checkBinary('sumo-gui') 19 | 20 | path_convert = get_abs_path(__file__) 21 | set_logger(path_convert('./')) 22 | 23 | sumocfg_file = path_convert(f"../../sumo_env/ego_crash/{CRASH_TYPE}/env.sumocfg") 24 | traci.start([sumoBinary, "-c", sumocfg_file, "--collision.action", "warn"], label='0') # 需要加入 collision.action 25 | conn = traci.getConnection('0') 26 | 27 | scene_vehicles = VehicleBuilder(sumo=conn, action_type='lane_continuous_speed') 28 | 29 | while conn.simulation.getMinExpectedNumber() > 0: 30 | # 获得车辆的信息 31 | data = scene_vehicles.get_objects_infos() 32 | 33 | actions = {} 34 | if "ego_1" in data: 35 | actions["ego_1"] = {'lane_change': 0, 'target_speed':12} 36 | if "ego_2" in data: 37 | actions["ego_2"] = {'lane_change': 0, 'target_speed':12} 38 | if "ego_3" in data: 39 | actions["ego_3"] = {'lane_change': 0, 'target_speed':12} 40 | if "ego_4" in data: 41 | actions["ego_4"] = {'lane_change': 0, 'target_speed':12} 42 | scene_vehicles.control_objects(actions) 43 | 44 | conn.simulationStep() 45 | 46 | conn.close() -------------------------------------------------------------------------------- /examples/vehicles/get_vehicle_state.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 15:50:00 4 | @Description: 获得场景中所有车辆的信息 5 | # 这里需要可以在每隔 Ns 获得当前车辆的所有信息 6 | @LastEditTime: 2024-04-09 21:12:05 7 | ''' 8 | import sumolib 9 | from loguru import logger 10 | 11 | from tshub.utils.get_abs_path import get_abs_path 12 | from tshub.vehicle.vehicle_builder import VehicleBuilder 13 | from tshub.utils.init_log import set_logger 14 | from tshub.utils.format_dict import dict_to_str 15 | 16 | import traci 17 | sumoBinary = sumolib.checkBinary('sumo-gui') 18 | 19 | path_convert = get_abs_path(__file__) 20 | set_logger(path_convert('./'), terminal_log_level='INFO') 21 | 22 | sumocfg_file = path_convert("../sumo_env/single_junction/env/single_junction.sumocfg") 23 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 24 | conn = traci.getConnection('0') 25 | 26 | scene_vehicles = VehicleBuilder(sumo=conn, action_type='lane') 27 | while conn.simulation.getMinExpectedNumber() > 0: 28 | data = scene_vehicles.get_objects_infos() # 获得车辆的信息 29 | logger.info(f'SIM: {dict_to_str(data)}') 30 | 31 | conn.simulationStep() 32 | 33 | conn.close() -------------------------------------------------------------------------------- /examples/vehicles/vehicle_action/vehicle_lane.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 16:55:45 4 | @Description: 控制车辆, 四个离散的动作 5 | @LastEditTime: 2024-08-11 19:28:00 6 | ''' 7 | import traci 8 | import random 9 | import numpy as np 10 | import sumolib 11 | 12 | from tshub.utils.get_abs_path import get_abs_path 13 | from tshub.vehicle.vehicle_builder import VehicleBuilder 14 | from tshub.utils.init_log import set_logger 15 | 16 | def select_keys(dictionary): 17 | keys = list(dictionary.keys()) 18 | selected_keys = random.sample(keys, k=int(len(keys) * 0.1)) 19 | return selected_keys 20 | 21 | sumoBinary = sumolib.checkBinary('sumo-gui') 22 | 23 | path_convert = get_abs_path(__file__) 24 | set_logger(path_convert('./')) 25 | 26 | sumocfg_file = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 27 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 28 | conn = traci.getConnection('0') 29 | 30 | scene_vehicles = VehicleBuilder(sumo=conn, action_type='lane') 31 | while conn.simulation.getMinExpectedNumber() > 0: 32 | # 获得车辆的信息 33 | data = scene_vehicles.get_objects_infos() 34 | 35 | # 控制部分车辆, 分别是 lane_change, speed 36 | selected_vehicles = select_keys(data) 37 | actions = { 38 | _veh_id:{'lane_change': np.random.randint(4)} 39 | for _veh_id in selected_vehicles 40 | } 41 | scene_vehicles.control_objects(actions) 42 | 43 | conn.simulationStep() 44 | 45 | conn.close() -------------------------------------------------------------------------------- /examples/vehicles/vehicle_action/vehicle_lane_with_continuous_speed.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-30 16:19:47 4 | @Description: 控制车辆, 同时控制换道和速度 5 | @LastEditTime: 2024-08-11 19:35:45 6 | ''' 7 | import traci 8 | import random 9 | import numpy as np 10 | import sumolib 11 | 12 | from tshub.utils.get_abs_path import get_abs_path 13 | from tshub.vehicle.vehicle_builder import VehicleBuilder 14 | from tshub.utils.init_log import set_logger 15 | 16 | def select_keys(dictionary): 17 | keys = list(dictionary.keys()) 18 | selected_keys = random.sample(keys, k=int(len(keys) * 0.1)) 19 | return selected_keys 20 | 21 | sumoBinary = sumolib.checkBinary('sumo-gui') 22 | 23 | path_convert = get_abs_path(__file__) 24 | set_logger(path_convert('./')) 25 | 26 | sumocfg_file = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 27 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 28 | conn = traci.getConnection('0') 29 | 30 | scene_vehicles = VehicleBuilder(sumo=conn, action_type='lane_continuous_speed') 31 | while conn.simulation.getMinExpectedNumber() > 0: 32 | # 获得车辆的信息 33 | data = scene_vehicles.get_objects_infos() 34 | 35 | # 控制部分车辆, 分别是 lane_change, speed 36 | selected_vehicles = select_keys(data) 37 | actions = { 38 | _veh_id:{'lane_change': np.random.randint(3), 'target_speed':12} 39 | for _veh_id in selected_vehicles 40 | } 41 | scene_vehicles.control_objects(actions) 42 | 43 | conn.simulationStep() 44 | 45 | conn.close() -------------------------------------------------------------------------------- /examples/vehicles/vehicle_action/vehicle_speed.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-08-11 18:50:35 4 | @Description: 单纯控制车辆的速度 5 | @LastEditTime: 2024-08-11 19:30:09 6 | ''' 7 | import traci 8 | import random 9 | import numpy as np 10 | import sumolib 11 | 12 | from tshub.utils.get_abs_path import get_abs_path 13 | from tshub.vehicle.vehicle_builder import VehicleBuilder 14 | from tshub.utils.init_log import set_logger 15 | 16 | def select_keys(dictionary): 17 | keys = list(dictionary.keys()) 18 | selected_keys = random.sample(keys, k=int(len(keys) * 1)) 19 | return selected_keys 20 | 21 | sumoBinary = sumolib.checkBinary('sumo-gui') 22 | 23 | path_convert = get_abs_path(__file__) 24 | set_logger(path_convert('./')) 25 | 26 | sumocfg_file = path_convert("../../sumo_env/single_junction/env/single_junction.sumocfg") 27 | traci.start([sumoBinary, "-c", sumocfg_file], label='0') 28 | conn = traci.getConnection('0') 29 | 30 | scene_vehicles = VehicleBuilder(sumo=conn, action_type='speed') 31 | while conn.simulation.getMinExpectedNumber() > 0: 32 | # 获得车辆的信息 33 | data = scene_vehicles.get_objects_infos() 34 | 35 | # 控制部分车辆, 分别是 lane_change, speed 36 | selected_vehicles = select_keys(data) 37 | actions = { 38 | _veh_id:{ 39 | 'speed_action': 1, # 0:加速, 1:减速, 2:保持不变 40 | 'acceleration_rate': 2, 41 | } 42 | for _veh_id in selected_vehicles 43 | } 44 | scene_vehicles.control_objects(actions) 45 | 46 | conn.simulationStep() 47 | 48 | conn.close() -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | loguru 2 | numpy 3 | traci 4 | sumolib 5 | libsumo 6 | scipy 7 | scienceplots -------------------------------------------------------------------------------- /test/test_tshub_version.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-26 05:21:00 4 | @Description: 检测是否安装成功 5 | @LastEditTime: 2024-07-26 05:23:51 6 | ''' 7 | import tshub 8 | import unittest 9 | from packaging import version 10 | 11 | class TestTSHubInstallation(unittest.TestCase): 12 | def test_version_greater_than_1(self) -> None: 13 | """Test if the installed TSHub package version is greater than 1. 14 | """ 15 | self.assertTrue(version.parse(tshub.__version__) >= version.parse("1.0")) 16 | 17 | if __name__ == '__main__': 18 | unittest.main() 19 | -------------------------------------------------------------------------------- /tshub/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 11:02:35 4 | @Description: tshub 5 | @LastEditTime: 2024-07-26 05:19:00 6 | ''' 7 | __TITLE__ = 'TransSimHub' 8 | __VERSION__ = 'v1.1' 9 | __DESCRIPTION__ = 'A lightweight Python library for simulating and controlling transportation systems' 10 | __AUTHOR__ = "Traffic-Alpha" 11 | __version__ = __VERSION__ -------------------------------------------------------------------------------- /tshub/aircraft/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/tshub/aircraft/__init__.py -------------------------------------------------------------------------------- /tshub/aircraft/aircraft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/tshub/aircraft/aircraft.png -------------------------------------------------------------------------------- /tshub/aircraft/aircraft_action_type.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-29 17:59:13 4 | @Description: Aircraft Action Type. Aircraft 共有四种动作类型,分别是: 5 | 1. 在固定的位置保持不动 6 | 2. 在固定的高度,只能水平面移动 7 | 3. 只能改变高度,水平方向无法移动 8 | 4. 可以同时改变高度和在水平方向移动,但是动作空间是离散的 9 | @LastEditTime: 2023-08-29 20:30:59 10 | ''' 11 | import enum 12 | 13 | class aircraft_action_type(enum.Enum): 14 | Stationary = 'stationary' 15 | """ 16 | Aircraft remains stationary at a fixed position. 17 | """ 18 | 19 | HorizontalMovement = 'horizontal_movement' 20 | """ 21 | Aircraft can only move in the horizontal plane while maintaining a fixed altitude. 22 | + Speed: float, 连续控制 23 | + Heading: int, 这里输入是 heading index, 平面内被分为 8 个 heading 角度 24 | """ 25 | 26 | VerticalMovement = 'vertical_movement' 27 | """ 28 | Aircraft can only change altitude while remaining in the same horizontal position. 29 | + Speed: float, 连续控制 30 | + Heading: int, 这里输入是 heading index, 共有三种情况, (1) 向上; (2) 向下; (3) 平稳 31 | """ 32 | 33 | CombinedMovement = 'combined_movement' 34 | """ 35 | Aircraft can simultaneously change altitude and move in the horizontal direction. The motion space is discrete. 36 | """ 37 | -------------------------------------------------------------------------------- /tshub/aircraft/aircraft_type/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-29 17:58:42 4 | @Description: 四种 aircraft 动作类型 5 | @LastEditTime: 2023-08-29 17:58:43 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/aircraft/aircraft_type/base_aircraft_action.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-29 20:18:04 4 | @Description: Base Aircraft Action 5 | @LastEditTime: 2023-08-30 18:18:56 6 | ''' 7 | from loguru import logger 8 | from typing import Tuple 9 | from abc import ABC, abstractmethod 10 | 11 | class AircraftAction(ABC): 12 | def __init__(self, id) -> None: 13 | super().__init__() 14 | self.aircraft_id = id 15 | 16 | @abstractmethod 17 | def execute(self) -> None: 18 | pass 19 | 20 | def calculate_new_position(self, 21 | position:Tuple[float, float, float], 22 | speed: float, heading:Tuple[float, float, float] 23 | ) -> Tuple[float, float, float]: 24 | new_position = [ 25 | position[0] + speed * heading[0], 26 | position[1] + speed * heading[1], 27 | position[2] + speed * heading[2] 28 | ] 29 | if new_position[2] <= 0: 30 | logger.warning(f'SIM: Aircraft 的高度不能小于 0, 现在高度为 {new_position[2]}.') 31 | logger.warning('SIM: Aircraft 的位置不变.') 32 | new_position[2] = position[2] # 保持原来的高度不变 33 | return new_position -------------------------------------------------------------------------------- /tshub/aircraft/aircraft_type/combined_movement.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-29 18:11:40 4 | @Description: 飞翔器水平和垂直同时移动 5 | @LastEditTime: 2023-08-30 16:05:22 6 | ''' 7 | import math 8 | from typing import Tuple 9 | from .base_aircraft_action import AircraftAction 10 | 11 | class CombinedMovementAction(AircraftAction): 12 | def __init__(self, id) -> None: 13 | super().__init__(id) 14 | AZIMUTHS = [0, 45, 90, 135, 180, 225, 270, 315] # Eight discrete azimuth angles 15 | ELEVATIONS = [-90, -45, 0, 45, 90] # Five discrete elevation angles 16 | self.combinations = [(azimuth, elevation) 17 | for azimuth in AZIMUTHS 18 | for elevation in ELEVATIONS 19 | ] 20 | 21 | def execute(self, 22 | position:Tuple[float, float, float], 23 | speed: float, heading_index: int) -> None: 24 | heading_combinations = self.combinations[heading_index] 25 | heading = self.calculate_heading_3d(*heading_combinations) 26 | new_position = self.calculate_new_position(position=position, speed=speed, heading=heading) 27 | return new_position, heading 28 | 29 | def calculate_heading_3d(self, azimuth:float, elevation:float) -> Tuple[float, float, float]: 30 | # 将方位角和俯仰角转换为弧度 31 | azimuth_rad = math.radians(azimuth) 32 | elevation_rad = math.radians(elevation) 33 | 34 | # 计算 heading 向量的 x、y 和 z 分量 35 | x = math.cos(azimuth_rad) * math.cos(elevation_rad) 36 | y = math.sin(azimuth_rad) * math.cos(elevation_rad) 37 | z = math.sin(elevation_rad) 38 | 39 | # 返回 heading 向量作为一个包含 x、y 和 z 分量的元组 40 | return (x, y, z) 41 | -------------------------------------------------------------------------------- /tshub/aircraft/aircraft_type/stationary.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-29 18:10:45 4 | @Description: 飞翔器保持不动 5 | @LastEditTime: 2023-08-30 15:31:05 6 | ''' 7 | from .base_aircraft_action import AircraftAction 8 | 9 | class StationaryAction(AircraftAction): 10 | def __init__(self, id) -> None: 11 | super().__init__(id) 12 | 13 | def execute(self, *args, **kwargs) -> None: 14 | position = kwargs['position'] 15 | heading = (0,0,0) # heading 为 0, 保持不变 16 | return position, heading -------------------------------------------------------------------------------- /tshub/aircraft/aircraft_type/vertical_movement.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-29 18:11:22 4 | @Description: 飞翔器垂直方向移动 5 | @LastEditTime: 2023-08-30 15:28:00 6 | ''' 7 | from typing import Tuple 8 | from .base_aircraft_action import AircraftAction 9 | 10 | class VerticalMovementAction(AircraftAction): 11 | HEADINGS = { 12 | 0: (0, 0, 0), # No change 13 | 1: (0, 0, 1), # Upward movement 14 | 2: (0, 0, -1) # Downward movement 15 | } 16 | 17 | def __init__(self, id) -> None: 18 | super().__init__(id) 19 | 20 | def execute(self, position:Tuple[float, float, float], 21 | speed: float, heading_index: int) -> None: 22 | heading = self.HEADINGS[heading_index] 23 | new_position = self.calculate_new_position(position=position, speed=speed, heading=heading) 24 | return new_position, heading 25 | 26 | -------------------------------------------------------------------------------- /tshub/features/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 15:46:27 4 | @Description: 5 | @LastEditTime: 2023-08-23 15:46:28 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/map/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-22 14:03:37 4 | @Description: Map Info and Builder 5 | @LastEditTime: 2023-09-22 14:03:41 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/person/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-24 15:47:03 4 | @Description: Person Info 5 | @LastEditTime: 2023-11-24 15:47:05 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/sumo_tools/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 13:37:55 4 | @Description: 关于 SUMO 使用的一些工具 5 | @LastEditTime: 2023-08-23 13:37:56 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/sumo_tools/additional_files/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-01 15:15:51 4 | @Description: 生成额外加载的 additional 文件 5 | @LastEditTime: 2023-09-01 15:15:52 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/sumo_tools/analysis_output/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-03-24 15:07:32 4 | @Description: 分析 SUMO Output 的文件 5 | @LastEditTime: 2024-03-24 15:08:00 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/sumo_tools/detectors/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-24 16:13:11 4 | @Description: 生成探测器 5 | @LastEditTime: 2023-08-24 16:13:12 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/sumo_tools/generate_route/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 14:16:05 4 | @Description: route 生成模块 5 | @LastEditTime: 2023-08-31 14:16:05 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/sumo_tools/interpolation/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 14:17:35 4 | @Description: 对 route 或是 turndef 进行插值 5 | @LastEditTime: 2023-08-31 14:17:36 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/sumo_tools/interpolation/repeat_values.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 17:01:13 4 | @Description: 5 | @LastEditTime: 2023-08-31 17:03:33 6 | ''' 7 | from typing import List 8 | 9 | def repeat_values(values, period) -> List[float]: 10 | """ 11 | 根据 period 列表中的数值,对 values 列表进行重复。 12 | 13 | 例如: 14 | + period 表示每个阶段的持续时间 (分钟); 15 | + values 表示每个阶段内每分钟的结果 16 | 17 | 例如: 18 | + values = [0.25, 0.5] # 每个时间段的转向比 19 | + period = [3, 3] # 每个时间段的持续时间 20 | -> 这里会转换为 [0.25, 0.25, 0.25, 0.5, 0.5, 0.5], 重复对应的次数 21 | 22 | 参数: 23 | values (list): 需要重复的数值。 24 | period (list): 每个时间段的持续时间列表。 25 | 26 | 返回: 27 | list: 重复后的结果。 28 | """ 29 | repeated_values = [] 30 | for i, num in enumerate(values): 31 | repeated_values.extend([num] * period[i]) 32 | return repeated_values -------------------------------------------------------------------------------- /tshub/sumo_tools/interpolation/visualize_interpolations.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 17:06:54 4 | @Description: 对插值之后的结果进行可视化展示 5 | @LastEditTime: 2023-08-31 17:16:20 6 | ''' 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | from .repeat_values import repeat_values 10 | 11 | def visualize_interpolations(values, period, smooth_values) -> None: 12 | """ 13 | 可视化原始转弯概率数据和平滑后的转弯概率数据。 14 | 15 | 参数: 16 | values (list): 每个周期内的值。 17 | period (int): 每个周期持续的时长。 18 | smooth_values (list): 平滑后的每分钟的值。 19 | """ 20 | # 创建时间间隔 21 | time_intervals = np.arange(len(smooth_values)) 22 | 23 | # 将 values 按照 period 重复 24 | repeated_values = repeat_values(values, period) 25 | 26 | # 绘制原始转弯概率数据 27 | plt.plot(time_intervals, repeated_values, 'o-', label='Original') 28 | # 绘制平滑后的转弯概率数据 29 | plt.plot(time_intervals, smooth_values, 's-', label='Smoothed') 30 | 31 | # 设置图表标题和轴标签 32 | plt.title('Comparison of Interpolations Results') 33 | plt.xlabel('Time Intervals') 34 | 35 | # 添加图例 36 | plt.legend() 37 | 38 | # 显示图表 39 | plt.show() -------------------------------------------------------------------------------- /tshub/sumo_tools/osm_build_type/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-05-27 16:11:27 4 | @Description: net & poly files 5 | @LastEditTime: 2024-05-27 16:11:28 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/sumo_tools/sumo_infos/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-24 17:06:29 4 | @Description: 从 SUMO 中提取结构化的数据 5 | @LastEditTime: 2023-08-24 17:06:30 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/sumo_tools/sumo_infos/traffic_light_ids.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-09-01 15:33:56 4 | @Description: 获得路网中所有的 traffic light 的 id 5 | @LastEditTime: 2023-09-01 15:36:42 6 | ''' 7 | import sumolib 8 | from typing import List 9 | 10 | def get_tlsID_list(network_file) -> List[str]: 11 | """返回一个路网文件所有的 Traffic Light Signal ID list 12 | 13 | Args: 14 | network_file (str): network 文件所在的路径 15 | 16 | Returns: 17 | list: tls id 组成的列表 18 | """ 19 | tls_list = [] 20 | net = sumolib.net.readNet(network_file) 21 | for node in net.getNodes(): 22 | if node.getType() == 'traffic_light': 23 | tls_list.append(node.getID()) 24 | return tls_list 25 | -------------------------------------------------------------------------------- /tshub/sumo_tools/sumo_infos/turndef/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2021-12-01 21:42:00 4 | @Description: 来自 tools/turn-defs/ 文件 5 | @LastEditTime: 2023-08-31 19:42:47 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/traffic_light/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-25 11:16:05 4 | @Description: traffic signal light module 5 | @LastEditTime: 2023-08-25 11:16:06 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/traffic_light/tls_type/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-25 17:08:46 4 | @Description: 不同的 Traffic Light Signal 的控制类型 (action design) 5 | @LastEditTime: 2024-04-24 16:32:40 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/traffic_light/traffic_light_action_type.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-25 16:55:36 4 | @Description: Traffic Light Signal Action Type 5 | @LastEditTime: 2024-06-27 19:00:42 6 | ''' 7 | import enum 8 | 9 | class tls_action_type(enum.Enum): 10 | ChooseNextPhase = 'choose_next_phase' 11 | """ 12 | Action= ``int``. Discrete action that can choose from all phases 13 | """ 14 | 15 | ChooseNextPhaseSyn = 'choose_next_phase_syn' 16 | """ 17 | Action= ``int``. Discrete action that can choose from all phases (Synchronize) 18 | """ 19 | 20 | NextorNot = 'next_or_not' 21 | """ 22 | Action= ``int``. Discrete action from one of 23 | 24 | + 0, Change to the next phase 25 | + 1, Keep the current phase 26 | """ 27 | 28 | AdjustCycleDuration = 'adjust_cycle_duration' 29 | """Action= ``List``. Fine-tuning of each phase duration 30 | """ 31 | 32 | SetPhaseDuration = 'set_phase_diration' 33 | """Action= ``int``. The new phase duration for the current traffic phase. 34 | """ -------------------------------------------------------------------------------- /tshub/traffic_light/traffic_light_feature_convert.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-25 19:37:07 4 | @Description: TSC 中 id 和 meaning 的转换 5 | @LastEditTime: 2023-09-11 19:56:28 6 | ''' 7 | class TSCKeyMeaningsConverter: 8 | def __init__(self): 9 | self.key_to_meaning = { 10 | 17: 'last_step_mean_speed', 11 | 18: 'last_step_vehicle_id_list', 12 | 24: 'jam_length_vehicle', 13 | 25: 'jam_length_meters', 14 | 19: 'last_step_occupancy', 15 | } 16 | self.meaning_to_key = {v: k for k, v in self.key_to_meaning.items()} 17 | 18 | def get_meaning(self, key): 19 | return self.key_to_meaning.get(key, '') 20 | 21 | def get_key(self, meaning): 22 | return self.meaning_to_key.get(meaning, '') 23 | -------------------------------------------------------------------------------- /tshub/tshub_env/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 15:34:58 4 | @Description: TransSimHub 环境 5 | @LastEditTime: 2023-08-23 15:34:59 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/tshub_env/base_builder.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-29 18:05:16 4 | @Description: builder 基类 5 | @LastEditTime: 2023-08-30 15:14:36 6 | ''' 7 | from abc import ABC, abstractmethod 8 | 9 | class BaseBuilder(ABC): 10 | @abstractmethod 11 | def create_objects(self) -> None: 12 | """创建场景内所有的 object 13 | """ 14 | pass 15 | 16 | @abstractmethod 17 | def update_objects_state(self) -> None: 18 | """更新场景内所有 object 的信息 19 | 1. 对于 vehicle 和 traffic light, 需要从 sumo 中获得信息来进行更新; 20 | 2. 对于 aircraft, 每次 control 之后自动进行更新; 21 | """ 22 | pass 23 | 24 | @abstractmethod 25 | def get_objects_infos(self) -> None: 26 | """返回场景内所有 object 的信息 27 | """ 28 | pass 29 | 30 | @abstractmethod 31 | def control_objects(self) -> None: 32 | """控制场景内所有的 objects 33 | """ 34 | pass -------------------------------------------------------------------------------- /tshub/tshub_env3d/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-03 16:01:43 4 | @Description: 将 TSHub 转换为 3D 的场景 5 | Modify according to the following two projects: 6 | - SMARTS, https://github.com/huawei-noah/SMARTS 7 | - MetaDrive, https://github.com/metadriverse/metadrive 8 | @LastEditTime: 2024-07-07 23:25:39 9 | ''' 10 | -------------------------------------------------------------------------------- /tshub/tshub_env3d/_assets_3d/map_road_lines/dashed_line_shader.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | out vec4 FragColor; 4 | 5 | flat in vec3 StartPos; 6 | in vec3 VertPos; 7 | 8 | uniform vec4 p3d_Color; 9 | uniform vec2 iResolution; 10 | 11 | void main() 12 | { 13 | uint pattern = 0x00FFu; 14 | float factor = 2.0; 15 | 16 | vec2 dir = (VertPos.xy - StartPos.xy) * iResolution / 2.0; 17 | float dist = length(dir); 18 | 19 | uint bit = uint(round(dist / factor)) & 15U; 20 | if ((pattern & (1U< None: 16 | """初始化的时候需要使用 self._follow_actor 初始化 sensor 的位置 17 | """ 18 | pass 19 | 20 | @abstractmethod 21 | def init_actor(self, element_pose) -> None: 22 | """初始化相机的位置 23 | """ 24 | raise NotImplementedError 25 | 26 | @abstractmethod 27 | def step(self, element_pose) -> None: 28 | """更新 camera 的位置, 确保可以获得指定 element 的信息 29 | """ 30 | raise NotImplementedError 31 | 32 | def teardown(self, **kwargs) -> None: 33 | self.camera.teardown() 34 | 35 | @property 36 | def serializable(self) -> bool: 37 | return False -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_renderer/sensors/base_sensors/base_sensor.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-07 22:26:18 4 | @Description: 定义基础的传感器 5 | @LastEditTime: 2024-07-08 23:32:36 6 | ''' 7 | import abc 8 | from typing import Any, Dict 9 | 10 | class BaseSensor(metaclass=abc.ABCMeta): 11 | """The sensor base class. 12 | """ 13 | def step(self, tshub_obs: Dict[str, Any], **kwargs): 14 | """Update sensor state (根据 TSHub 返回值更新 sensor). 15 | """ 16 | pass 17 | 18 | @abc.abstractmethod 19 | def teardown(self, **kwargs): 20 | """Clean up internal resources 21 | """ 22 | raise NotImplementedError 23 | 24 | @abc.abstractmethod 25 | def __call__(self, *args: Any, **kwds: Any) -> Any: 26 | raise NotImplementedError 27 | 28 | @property 29 | def mutable(self) -> bool: 30 | """If this sensor mutates on call.""" 31 | return True 32 | 33 | @property 34 | def serializable(self) -> bool: 35 | """If this sensor can be serialized.""" 36 | return True -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_renderer/sensors/cameras/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-07 22:03:33 4 | @Description: 场景相机, 包含 Off-screen camera & Shader camera 5 | @LastEditTime: 2024-07-07 22:03:33 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_renderer/sensors/cameras/offscreen_camera/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-15 11:52:22 4 | @Description: 创建基础相机组建 5 | @LastEditTime: 2024-07-21 03:14:48 6 | ''' 7 | from .bev_camera import OffscreenBEVCamera 8 | from .aircraft_camera import OffscreenAircraftCamera 9 | 10 | from .front_camera import ( 11 | OffscreenFrontCamera, 12 | OffscreenFrontLeftCamera, 13 | OffscreenFrontRightCamera, 14 | ) 15 | 16 | from .back_camera import ( 17 | OffscreenBackCamera, 18 | OffscreenBackLeftCamera, 19 | OffscreenBackRightCamera 20 | ) 21 | 22 | from .junction_camera import ( 23 | OffscreenJunctionFrontCamera, 24 | OffscreenJunctionBackCamera, 25 | ) -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_renderer/sensors/cameras/offscreen_camera/aircraft_camera.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-21 03:08:43 4 | @Description: 飞行器上面的飞行器 5 | @LastEditTime: 2024-07-21 03:58:09 6 | ''' 7 | from typing import Tuple 8 | from dataclasses import dataclass 9 | 10 | from .base_offscreen_camera import ( 11 | BaseOffscreenCamera, 12 | _BaseOffCameraMixin 13 | ) 14 | from .....vis3d_utils.coordinates import Pose 15 | 16 | @dataclass 17 | class OffscreenAircraftCamera(_BaseOffCameraMixin, BaseOffscreenCamera): 18 | """无人机上面的相机, 从无人机往下拍 19 | """ 20 | def init_pos(self, pose:Pose, *args, **kwargs) -> None: 21 | """初始化 camera 的位置 22 | """ 23 | self.update(pose, *args, **kwargs) 24 | 25 | def update(self, pose: Pose, *args, **kwargs) -> None: 26 | """Update the location of the camera (这里 Update 可以使得 camera 跟踪车辆或是其他的 object). 27 | Args: 28 | pose: 29 | The pose of the camera target. 30 | height: 31 | The height of the camera above the camera target. 32 | """ 33 | pos, heading = pose.as_panda3d() 34 | # 俯视的角度 35 | self.camera_np.setPos(pos[0], pos[1], pos[2]) 36 | self.camera_np.lookAt(pos[0], pos[1], 2) # 查看 UAV/UAM 正下方 37 | # self.camera_np.setH(heading) # 航向角 38 | 39 | @property 40 | def position(self) -> Tuple[float, float, float]: 41 | return self.camera_np.getPos() -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_renderer/sensors/cameras/offscreen_camera/base_offscreen_camera/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-20 14:33:19 4 | @Description: Base Class for Offscreen Camera 5 | @LastEditTime: 2024-07-20 14:38:38 6 | ''' 7 | from .base_off_camera import BaseOffscreenCamera 8 | from .base_off_camera_mixin import _BaseOffCameraMixin -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_renderer/sensors/cameras/offscreen_camera/bev_camera.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-07 22:04:09 4 | @Description: BEV Camera (俯视摄像头) 5 | @LastEditTime: 2024-07-21 03:11:56 6 | ''' 7 | from typing import Tuple 8 | from dataclasses import dataclass 9 | 10 | from .base_offscreen_camera import ( 11 | BaseOffscreenCamera, 12 | _BaseOffCameraMixin 13 | ) 14 | from .....vis3d_utils.coordinates import Pose 15 | 16 | @dataclass 17 | class OffscreenBEVCamera(_BaseOffCameraMixin, BaseOffscreenCamera): 18 | """A camera used for rendering images to a graphics buffer (这里是 BEV 的视角). 19 | """ 20 | def init_pos(self, pose:Pose, height:float=30, *args, **kwargs) -> None: 21 | """初始化 camera 的位置 22 | """ 23 | self.update(pose, height, *args, **kwargs) 24 | 25 | def update(self, pose: Pose, height:float=30, *args, **kwargs) -> None: 26 | """Update the location of the camera (这里 Update 可以使得 camera 跟踪车辆或是其他的 object). 27 | Args: 28 | pose: 29 | The pose of the camera target. 30 | height: 31 | The height of the camera above the camera target. 32 | """ 33 | pos, heading = pose.as_panda3d() 34 | # 俯视的角度 35 | self.camera_np.setPos(pos[0], pos[1], pos[2]+height) 36 | self.camera_np.lookAt(pos[0], pos[1], 2) # 查看 UAV/UAM 正下方 37 | self.camera_np.setH(heading) # 航向角, 这样让车道正前方 38 | 39 | @property 40 | def position(self) -> Tuple[float, float, float]: 41 | return self.camera_np.getPos() -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_renderer/sensors/cameras/offscreen_camera/offscreen_camera_type.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-15 12:12:53 4 | @Description: Offscreen Camera 的类型 5 | @LastEditTime: 2024-07-21 03:13:42 6 | ''' 7 | import enum 8 | 9 | class OffscreenCameraType(enum.Enum): 10 | # 十字路口摄像头 11 | Junction_Front = "Off_Junction_Front_Camera" 12 | Junction_Back = "Off_Junction_Back_Camera" 13 | # 摄像头在前方 14 | Front = 'Off_Front_Camera' 15 | Front_LEFT = 'Off_FrontLeft_Camera' 16 | Front_RIGHT = 'Off_FrontRight_Camera' 17 | # 摄像头在后方 18 | Back = 'Off_Back_Camera' 19 | Back_LEFT = 'Off_BackLeft_Camera' 20 | Back_RIGHT = 'Off_BackRight_Camera' 21 | # 跟随车辆的视角 22 | BEV = 'Off_BEV_Camera' 23 | # 无人机的视角 24 | Aircraft = 'Off_Aircraft_Camera' -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_renderer/traffic_elements/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-08 21:49:27 4 | @Description: 3D 场景内基本的物体 5 | @LastEditTime: 2024-07-08 23:11:24 6 | ''' -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_sumonet_convert/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-03 23:28:34 4 | @Description: 路网转换的工具 5 | @LastEditTime: 2024-07-03 23:28:34 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_sumonet_convert/element_to_glb/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-13 07:25:27 4 | @Description: 分别将地图元素转换为 glb 5 | @LastEditTime: 2024-07-13 07:43:21 6 | ''' 7 | import trimesh 8 | from typing import Final 9 | 10 | OLD_TRIMESH: Final[bool] = tuple(int(d) for d in trimesh.__version__.split(".")) <= ( 11 | 3, 12 | 9, 13 | 29, 14 | ) -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_sumonet_convert/element_to_glb/road_glb.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-13 07:27:10 4 | @Description: 生成 road glb 文件 5 | @LastEditTime: 2024-07-13 07:51:47 6 | ''' 7 | import math 8 | import warnings 9 | from typing import List, Tuple 10 | 11 | import numpy as np 12 | import trimesh.visual 13 | 14 | from ...vis3d_utils.colors import Colors 15 | from ..sumonet_convert_utils.glb_data import GLBData 16 | 17 | # Suppress trimesh deprecation warning 18 | with warnings.catch_warnings(): 19 | warnings.filterwarnings( 20 | "ignore", 21 | message="Please use `coo_matrix` from the `scipy.sparse` namespace, the `scipy.sparse.coo` namespace is deprecated.", 22 | category=DeprecationWarning, 23 | ) 24 | import trimesh # only suppress the warnings caused by trimesh 25 | from trimesh.exchange import gltf 26 | 27 | def make_road_glb(lines: List[List[Tuple[float, float]]]) -> GLBData: 28 | """Create a GLB file from a list of road lines (使用实线连接). 29 | """ 30 | scene = trimesh.Scene() 31 | for line_pts in lines: 32 | # Create a list of vertices with a z-coordinate of 0.1 33 | vertices = np.array([(*pt, 0.1) for pt in line_pts]) 34 | # Create a Path3D directly from the vertices 35 | path = trimesh.load_path(vertices) 36 | path.apply_transform( 37 | trimesh.transformations.rotation_matrix(math.pi / 2, [-1, 0, 0]) 38 | ) 39 | path.visual = trimesh.visual.ColorVisuals( 40 | vertex_colors=np.array([Colors.White.value for _ in range(len(vertices))]) 41 | ) 42 | scene.add_geometry(path) 43 | return GLBData(gltf.export_glb(scene)) -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_sumonet_convert/map_elements/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-13 05:02:54 4 | @Description: 路网的基础组成部分 5 | @LastEditTime: 2024-07-13 05:02:55 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_sumonet_convert/map_elements/surface.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-05 19:10:34 4 | @Description: 定义 SUMO Surface 5 | @LastEditTime: 2024-07-13 05:10:54 6 | ''' 7 | import itertools 8 | from typing import List, Optional 9 | 10 | from .base_road_map import RoadMap 11 | from ...vis3d_utils.coordinates import Pose 12 | 13 | class Surface(RoadMap.Surface): 14 | """Describes a Sumo surface (lane & road). 15 | """ 16 | def __init__(self, surface_id: str, road_map): 17 | self._surface_id = surface_id 18 | self._map = road_map 19 | self._features = dict() 20 | 21 | @property 22 | def surface_id(self) -> str: 23 | return self._surface_id 24 | 25 | @property 26 | def is_drivable(self) -> bool: 27 | # all surfaces on SUMO road networks are drivable 28 | return True 29 | 30 | @property 31 | def features(self) -> List[RoadMap.Feature]: 32 | return list(self._features.values()) 33 | 34 | def features_near(self, pose: Pose, radius: float) -> List[RoadMap.Feature]: 35 | pt = pose.point 36 | return [ 37 | feat 38 | for feat in self._features.values() 39 | if radius >= feat.min_dist_from(pt) 40 | ] 41 | 42 | def surface_by_id(self, surface_id: str) -> Optional[RoadMap.Surface]: 43 | return self._surfaces.get(surface_id) 44 | 45 | @staticmethod 46 | def pairwise(iterable): 47 | """Generates pairs of neighboring elements. 48 | >>> list(pairwise('ABCDEFG')) 49 | [('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'E'), ('E', 'F'), ('F', 'G')] 50 | """ 51 | a, b = itertools.tee(iterable) 52 | next(b, None) 53 | return zip(a, b) -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_sumonet_convert/sumonet_convert_utils/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-13 07:34:19 4 | @Description: 路网转换工具 5 | @LastEditTime: 2024-07-13 07:34:19 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_sumonet_convert/sumonet_convert_utils/geometry.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-03 16:13:17 4 | @Description: 路网转换的小工具 5 | Reference, https://github.com/huawei-noah/SMARTS/blob/master/smarts/core/utils/geometry.py 6 | @LastEditTime: 2024-07-13 07:21:38 7 | ''' 8 | from shapely.ops import triangulate 9 | from shapely.geometry import LineString, MultiPolygon, Polygon 10 | from shapely.geometry.base import CAP_STYLE, JOIN_STYLE 11 | 12 | def buffered_shape(shape, width: float = 1.0) -> Polygon: 13 | """收一个形状(shape)和一个宽度(width)作为参数, 14 | 然后生成一个在原始形状周围添加了宽度为 width 的缓冲区的新形状 15 | """ 16 | ls = LineString(shape).buffer( 17 | width / 2, 18 | 1, 19 | cap_style=CAP_STYLE.flat, 20 | join_style=JOIN_STYLE.round, 21 | mitre_limit=5.0, 22 | ) 23 | if isinstance(ls, MultiPolygon): 24 | # Sometimes it oddly outputs a MultiPolygon and then we need to turn it into a convex hull 25 | ls = ls.convex_hull # 将其转换为凸包(convex hull) 26 | elif not isinstance(ls, Polygon): 27 | raise RuntimeError("Shapely `object.buffer` behavior may have changed.") 28 | return ls 29 | 30 | 31 | def triangulate_polygon(polygon: Polygon): 32 | """Attempts to convert a polygon into triangles. 33 | """ 34 | # XXX: shapely.ops.triangulate current creates a convex fill of triangles. 35 | return [ 36 | tri_face 37 | for tri_face in triangulate(polygon) 38 | if tri_face.centroid.within(polygon) 39 | ] -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_sumonet_convert/sumonet_convert_utils/glb_data.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-13 07:28:05 4 | @Description: GLB Class 5 | @LastEditTime: 2024-07-13 07:28:05 6 | ''' 7 | from pathlib import Path 8 | from typing import Union 9 | 10 | class GLBData: 11 | """Convenience class for writing GLB files. 12 | """ 13 | def __init__(self, bytes_) -> None: 14 | self._bytes = bytes_ 15 | 16 | def write_glb(self, output_path: Union[str, Path]) -> None: 17 | """Generate a geometry file.""" 18 | with open(output_path, "wb") as f: 19 | f.write(self._bytes) -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_utils/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-03 16:02:23 4 | @Description: 3d 可视化的辅助工具 5 | 1. 将 SUMO Net 转换为 3D 模型 6 | 2. 不同交通参与者对应的 3D 模型 7 | 3. 8 | @LastEditTime: 2024-07-03 16:02:24 9 | ''' 10 | -------------------------------------------------------------------------------- /tshub/tshub_env3d/vis3d_utils/masks.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-07-06 20:56:50 4 | @Description: 定义 Masks, 决定哪些对象会被渲染 5 | @LastEditTime: 2024-07-14 20:26:47 6 | ''' 7 | from panda3d.core import BitMask32 8 | 9 | class RenderMasks: 10 | """Rendering mask flags 11 | """ 12 | NONE = 0x00 # 没有任何对象被隐藏,所有对象都会被渲染 13 | OCCUPANCY_HIDE = 0x01 # 隐藏那些被标记为 "occupancy" 的对象 14 | RGB_HIDE = 0x02 # 用于隐藏那些被标记为 "RGB" 的对象 15 | DRIVABLE_AREA_HIDE = 0x04 # 用于隐藏那些被标记为 "drivable area" 的对象 16 | 17 | class CamMask(): 18 | AllOn = BitMask32.allOn() # 全部是 1 19 | AllOff = BitMask32.allOff() # 全部是 0 20 | VehMask = BitMask32.bit(1) # 车辆的 mask 21 | MapMask = BitMask32.bit(2) # 环境 mask, 包括 map, road, line 22 | GroundMask = BitMask32.bit(3) # 环境的 ground 23 | SkyBoxMask = BitMask32.bit(4) # skybox -------------------------------------------------------------------------------- /tshub/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Traffic-Alpha/TransSimHub/339d051fbfb27daba060521b57321ace68a290b5/tshub/utils/__init__.py -------------------------------------------------------------------------------- /tshub/utils/check_folder.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2021-11-19 15:11:24 4 | @Description: 判断文件夹是否存在, 不存在则创建 5 | @LastEditTime: 2023-08-24 17:01:27 6 | ''' 7 | import os 8 | from loguru import logger 9 | 10 | def check_folder(folder_path) -> None: 11 | """判断文件夹是否存在, 如果不存在则进行创建 12 | 13 | Args: 14 | folder_path (str): 文件夹的路径 15 | """ 16 | if not os.path.isdir(folder_path): # 判断路径是否存在 17 | os.makedirs(folder_path, exist_ok=True) # 不存在则创建 18 | logger.warning('SIM: 文件夹 {} 不存在, 已创建!'.format(folder_path)) -------------------------------------------------------------------------------- /tshub/utils/format_dict.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-24 17:34:14 4 | @Description: 将 dict 转换为字符串, 带有环行 5 | LastEditTime: 2025-03-21 11:21:05 6 | ''' 7 | import json 8 | import numpy as np 9 | from loguru import logger 10 | 11 | def dict_to_str(my_dict) -> str: 12 | """将字典转换为格式化的 JSON 字符串 13 | """ 14 | def convert_to_serializable(obj): 15 | if isinstance(obj, np.ndarray): 16 | return obj.tolist() # 将ndarray转换为列表 17 | raise TypeError(f"Object of type {type(obj)} is not JSON serializable") 18 | 19 | json_str = json.dumps(my_dict, indent=4, default=convert_to_serializable) 20 | return json_str 21 | 22 | def save_str_to_json(my_dict, file_path:str, indent:int=4) -> None: 23 | """将 dict 串保存为 JSON 文件 24 | """ 25 | with open(file_path, 'w', encoding='utf-8') as f: 26 | json.dump(my_dict, f, ensure_ascii=False, indent=indent) 27 | logger.info(f'SIM: 字典已成功保存到 {file_path}') -------------------------------------------------------------------------------- /tshub/utils/get_abs_path.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 11:27:57 4 | @Description: 将相对路径转换为绝对路径 5 | @LastEditTime: 2023-08-24 17:01:22 6 | ''' 7 | import os 8 | from loguru import logger 9 | from typing import Optional 10 | 11 | class get_abs_path(object): 12 | 13 | def __init__(self, file_abspath: Optional[str] = None) -> None: 14 | self.file_abspath = file_abspath # 当前文件的完整路径 15 | 16 | def __call__(self, file_relpath: str): 17 | """将相对路径转换为绝对路径 18 | """ 19 | if self.file_abspath is None: 20 | logger.warning('SIM: 没有设置当前文件路径') 21 | self.file_abspath = os.path.abspath(__file__) 22 | 23 | folder_abspath = os.path.dirname(self.file_abspath) 24 | return os.path.join(folder_abspath, file_relpath) -------------------------------------------------------------------------------- /tshub/utils/nested_dict_conversion.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-24 16:16:20 4 | @Description: 处理 defaultdict 5 | @LastEditTime: 2023-08-24 16:20:55 6 | ''' 7 | from collections import defaultdict 8 | from typing import Union 9 | 10 | def create_nested_defaultdict() -> defaultdict: 11 | """生成无限嵌套的 defaultdict 12 | """ 13 | return defaultdict(create_nested_defaultdict) 14 | 15 | 16 | def defaultdict2dict(data: Union[defaultdict, dict]) -> dict: 17 | """将嵌套的 defaultdict 转换为普通的 dict 18 | """ 19 | if isinstance(data, dict): 20 | return {k: defaultdict2dict(v) for k, v in data.items()} 21 | else: 22 | return data -------------------------------------------------------------------------------- /tshub/utils/normalization_dict.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-31 17:53:38 4 | @Description: 字典中的值归一化, 使其和为 1 5 | @LastEditTime: 2023-08-31 17:55:06 6 | ''' 7 | def normalize_dict(input_dict): 8 | """ 9 | 将字典中的值归一化,使其和为1。例如: 10 | + Input: a = {1:1, 2:2, 3:3}, 11 | + Output: {1: 0.16666666666666666, 2: 0.3333333333333333, 3: 0.5} 12 | 13 | Args: 14 | input_dict (dict): 输入的字典数据。 15 | 16 | Returns: 17 | dict: 归一化后的字典。 18 | """ 19 | # 计算字典值的总和 20 | total_value = sum(input_dict.values()) 21 | 22 | # 归一化字典 23 | normalized_dict = {key: value / total_value for key, value in input_dict.items()} 24 | 25 | return normalized_dict 26 | -------------------------------------------------------------------------------- /tshub/utils/plt_to_array.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-13 21:25:42 4 | @Description: 将 fig 转换为 array, for render 5 | @LastEditTime: 2023-12-01 14:36:43 6 | ''' 7 | import numpy as np 8 | 9 | def plt2arr(fig): 10 | """ 11 | need to draw if figure is not drawn yet 12 | """ 13 | fig.canvas.draw() 14 | rgba_buf = fig.canvas.buffer_rgba() 15 | (w,h) = fig.canvas.get_width_height() 16 | rgba_arr = np.frombuffer(rgba_buf, dtype=np.uint8).reshape((h,w,4)) 17 | return rgba_arr -------------------------------------------------------------------------------- /tshub/v2x/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-08-09 11:26:23 4 | @Description: Channel Models 5 | @LastEditTime: 2024-08-10 20:22:07 6 | ''' 7 | from .v2x_channel import V2XChannel 8 | from .v2i_channel import V2IChannel 9 | from .v2v_channel import V2VChannel 10 | 11 | from .v2x_utils.snr_to_packetloss import calculate_outage_probability -------------------------------------------------------------------------------- /tshub/v2x/v2x_utils/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-08-10 18:00:50 4 | @Description: 包含 v2x 的工具, 例如将 SNR 转换为 packet loss 等 5 | @LastEditTime: 2024-08-10 18:01:52 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/v2x/v2x_utils/snr_to_packetloss.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-08-10 20:18:53 4 | @Description: 将 SNR 转换为 Packet Loss 5 | @LastEditTime: 2024-08-10 20:27:00 6 | ''' 7 | import numpy as np 8 | 9 | def calculate_outage_probability(snr_db, bandwidth_hz=30e3, target_rate_bps=20e3): 10 | """ 11 | Calculate the outage probability in a Rayleigh fading channel. 12 | 13 | Parameters: 14 | snr_db (float): The signal-to-noise ratio in decibels (dB). 15 | bandwidth_hz (float): The channel bandwidth in Hertz (default is 30kHz). 16 | target_rate_bps (float): The target rate in bits per second (default is 20kb/s). 17 | 18 | Returns: 19 | float: The calculated outage probability. 20 | """ 21 | # Convert SNR from dB to linear scale 22 | snr_linear = 10 ** (snr_db / 10) 23 | 24 | # Calculate the threshold u based on the target rate and SNR 25 | u_threshold = (2 ** (target_rate_bps / bandwidth_hz) - 1) / snr_linear 26 | 27 | # Calculate the outage probability 28 | outage_probability = 1 - np.exp(-u_threshold) 29 | 30 | return outage_probability -------------------------------------------------------------------------------- /tshub/vehicle/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 15:18:54 4 | @Description: vehicle data and controller 5 | @LastEditTime: 2023-08-23 15:18:55 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/vehicle/vehicle_action_type.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-23 17:03:19 4 | @Description: Vehicle Action Type 5 | - 这两种动作都是设置变道和速度,在底层就是直接调用 SUMO 来进行控制的 6 | @LastEditTime: 2024-08-11 18:42:36 7 | ''' 8 | import enum 9 | 10 | class vehicle_action_type(enum.Enum): 11 | Lane = 'lane' 12 | """ 13 | Action= ``str``. Discrete lane action from one of 14 | 15 | + "keep_lane", 16 | + "slow_down", 17 | + "change_lane_left", and 18 | + "change_lane_right". 19 | """ 20 | 21 | Speed = 'speed' 22 | """ 23 | Action= ``str``. Discrete speed action from one of 24 | 25 | + "accelerate", 26 | + "decelerate", 27 | + "maintain_speed". 28 | """ 29 | 30 | LaneWithContinuousSpeed = 'lane_continuous_speed' 31 | """ 32 | Action=(target_speed, lane_change). 33 | 34 | + target_speed: Baseline target speed (controller may give more or less regardless). Type=float. 35 | + lane_change: Discrete lane change value. Can be one of 36 | + -1 : change to right lane 37 | + 0 : keep to current lane 38 | + 1 : change to left lane 39 | """ -------------------------------------------------------------------------------- /tshub/vehicle/vehicle_type/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-25 17:57:35 4 | @Description: 不同的 vehicle 控制类型 5 | @LastEditTime: 2024-08-11 18:48:04 6 | ''' 7 | from .lane import LaneAction 8 | from .speed import SpeedAction 9 | from .lane_with_continuous_speed import LaneWithContinuousSpeedAction -------------------------------------------------------------------------------- /tshub/vehicle/vehicle_type/lane_with_continuous_speed.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-08-28 18:24:56 4 | @Description: 变车道+连续速度控制 5 | @LastEditTime: 2024-08-11 18:58:02 6 | ''' 7 | import enum 8 | from loguru import logger 9 | from .base_vehicle_action import VehicleAction 10 | 11 | class LaneChangeActionType(enum.Enum): 12 | default = -1 13 | keep_lane = 0 14 | change_lane_left = 1 15 | change_lane_right = 2 16 | 17 | class LaneWithContinuousSpeedAction(VehicleAction): 18 | def __init__(self, id, vehicle_type, sumo) -> None: 19 | super().__init__(id, vehicle_type, sumo) 20 | 21 | def execute(self, lane_change:int, target_speed:float, 22 | current_lane_index:int, current_road_id:str, 23 | *args, **kwargs, 24 | ) -> None: 25 | lane_change = LaneChangeActionType(lane_change) 26 | if lane_change == LaneChangeActionType.keep_lane: 27 | self.change_lane(0, current_lane=current_lane_index, current_edge=current_road_id) 28 | elif lane_change == LaneChangeActionType.change_lane_left: 29 | self.change_lane(1, current_lane=current_lane_index, current_edge=current_road_id) 30 | elif lane_change == LaneChangeActionType.change_lane_right: 31 | self.change_lane(-1, current_lane=current_lane_index, current_edge=current_road_id) 32 | elif lane_change == LaneChangeActionType.default: 33 | logger.debug(f'SIM: SUMO Control Lane Change Automatic') 34 | 35 | if target_speed != -1: # If we set target speed to -1, then speed of the vehicle will not change 36 | self.sumo.vehicle.slowDown(self.veh_id, target_speed, duration=1) 37 | else: 38 | logger.debug(f'SIM: SUMO Set Speed Automatic') 39 | -------------------------------------------------------------------------------- /tshub/vehicle/vehicle_type/speed.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2024-08-11 18:38:39 4 | @Description: 控制速度, 变道由 SUMO 控制 5 | @LastEditTime: 2024-08-11 19:35:01 6 | ''' 7 | import enum 8 | from loguru import logger 9 | from .base_vehicle_action import VehicleAction 10 | 11 | class SpeedActionType(enum.Enum): 12 | accelerate = 0 # 加速 13 | decelerate = 1 # 减速 14 | maintain_speed = 2 # 保持不变 15 | 16 | class SpeedAction(VehicleAction): 17 | def __init__(self, id, vehicle_type, sumo) -> None: 18 | super().__init__(id, vehicle_type, sumo) 19 | 20 | def execute(self, 21 | current_speed: float, speed_action: SpeedActionType, 22 | acceleration_rate:float=2, # m/s 23 | *args, **kwargs, 24 | ) -> None: 25 | action = SpeedActionType(speed_action) 26 | # Speed control logic 27 | if action == SpeedActionType.accelerate: 28 | new_speed = current_speed + acceleration_rate 29 | logger.info(f'SIM: 车辆 {self.veh_id} 加速到 {new_speed}.') 30 | self.sumo.vehicle.setSpeed(self.veh_id, new_speed) 31 | elif action == SpeedActionType.decelerate: 32 | new_speed = max(1, current_speed - acceleration_rate) # Prevent negative speed 33 | logger.info(f'SIM: 车辆 {self.veh_id} 减速到 {new_speed}.') 34 | self.sumo.vehicle.setSpeed(self.veh_id, new_speed) 35 | elif action == SpeedActionType.maintain_speed: 36 | # No change to the vehicle's speed 37 | pass 38 | else: 39 | logger.debug(f'SIM: SUMO Speed Action Unknown') 40 | -------------------------------------------------------------------------------- /tshub/visualization/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-12 16:19:10 4 | @Description: Visualization for TsHub Env 5 | @LastEditTime: 2023-11-12 16:19:11 6 | ''' 7 | -------------------------------------------------------------------------------- /tshub/visualization/vis_map_feature.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-12 16:20:15 4 | @Description: 对地图元素的可视化 5 | @LastEditTime: 2023-11-12 22:50:08 6 | ''' 7 | from matplotlib.lines import Line2D 8 | 9 | def plot_map_feature(ax, map_edges, map_nodes) -> None: 10 | # Draw edges 11 | for _, edge_info in map_edges.items(): 12 | edge_shape = edge_info.get('shape') 13 | for i in range(len(edge_shape)): 14 | x_values = [edge_shape[i - 1][0], edge_shape[i][0]] 15 | y_values = [edge_shape[i - 1][1], edge_shape[i][1]] 16 | line = Line2D(x_values, y_values, linewidth=1, color='grey', linestyle='-') 17 | ax.add_line(line) 18 | 19 | # Draw nodes 20 | for _, node_info in map_nodes.items(): 21 | node_shape = node_info.get('shape') 22 | for i in range(len(node_shape)): 23 | x_values = [node_shape[i - 1][0], node_shape[i][0]] 24 | y_values = [node_shape[i - 1][1], node_shape[i][1]] 25 | line = Line2D(x_values, y_values, linewidth=3, color='grey', linestyle='--') 26 | ax.add_line(line) 27 | 28 | -------------------------------------------------------------------------------- /tshub/visualization/visualize_map.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @Author: WANG Maonan 3 | @Date: 2023-11-12 16:22:16 4 | @Description: 对地图的可视化 5 | @LastEditTime: 2023-11-13 19:21:58 6 | ''' 7 | import matplotlib.pyplot as plt 8 | 9 | from .vis_map_feature import plot_map_feature 10 | from .vis_vehicles import plot_vehicle 11 | 12 | def render_map(focus_id, map_edges, map_nodes, vehicles, x_range, y_range): 13 | fig, ax = plt.subplots(figsize=(6, 6)) 14 | 15 | plot_map_feature(ax, map_edges, map_nodes) 16 | plot_vehicle(ax, focus_id, vehicles) 17 | 18 | ax.set_axis_off() # 去掉 x,y 轴 19 | plt.axis('equal') # x,y 的比例一样 20 | 21 | # 设置 x 和 y 轴的范围 22 | ax.set_xlim(x_range) 23 | ax.set_ylim(y_range) 24 | 25 | fig = plt.gcf() # 获得当前的图像 26 | return fig 27 | --------------------------------------------------------------------------------