diff --git a/.gitignore b/.gitignore index c862ec277a8e310ff9b8c4b26eecfe81111ee68a..03a577b0b713ed8adadda7f6f583e58774f99186 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ venv/ **.egg-info/ .VSCodeCounter/ dist/dryvr_plus_plus-0.1-py3.8.egg -tmp/ \ No newline at end of file +tmp/ +dist/ \ No newline at end of file diff --git a/demo/ball_bounces.py b/demo/ball_bounces.py index 943a2c720b4490a43667489a6c2a484abbeb1ec8..31dfb96043b89ebe2a6e283572c78ad8299c9a40 100644 --- a/demo/ball_bounces.py +++ b/demo/ball_bounces.py @@ -1,7 +1,7 @@ from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor4 import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * +from dryvr_plus_plus.plotter.plotter2D import * from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap3 from dryvr_plus_plus.scene_verifier.scenario.scenario import Scenario from dryvr_plus_plus.example.example_agent.ball_agent import BallAgent diff --git a/demo/demo1.py b/demo/demo1.py index 8290e0ba23e4dd19bbe60aca418514d560072081..e6afd9f8742a76d703209867166890387e66b88f 100644 --- a/demo/demo1.py +++ b/demo/demo1.py @@ -4,7 +4,7 @@ from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMa from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor2 from enum import Enum, auto import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * +from dryvr_plus_plus.plotter.plotter2D import * class VehicleMode(Enum): diff --git a/demo/demo10.py b/demo/demo10.py index 3a1f78481c7c7d072432b1de9fd12158b416c87f..64c4477681ed2625e7fd8c72f319e6200c02c90e 100644 --- a/demo/demo10.py +++ b/demo/demo10.py @@ -1,13 +1,11 @@ from dryvr_plus_plus.example.example_agent.car_agent import CarAgent from dryvr_plus_plus.scene_verifier.scenario.scenario import Scenario from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMap3, SimpleMap5, SimpleMap6, SimpleMap3_v2 -from dryvr_plus_plus.plotter.plotter2D import * -from dryvr_plus_plus.plotter.plotter2D_new import * from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor2 +from dryvr_plus_plus.plotter.plotter2D import * from enum import Enum, auto import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * class VehicleMode(Enum): diff --git a/demo/demo2.py b/demo/demo2.py index f5b27b7b643bc222ebdf555575ab68ef11e2c2b2..60c006f06681d26b6935385327d3bfea8a8a5776 100644 --- a/demo/demo2.py +++ b/demo/demo2.py @@ -4,7 +4,7 @@ from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMa from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor2 from enum import Enum, auto import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * +from dryvr_plus_plus.plotter.plotter2D import * import numpy as np diff --git a/demo/demo3.py b/demo/demo3.py index edb2982c846d4b1af3933c49eea49ab325e80e2a..ad03b3005035078fb2e12231c670a98727ac382a 100644 --- a/demo/demo3.py +++ b/demo/demo3.py @@ -5,7 +5,7 @@ from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMa from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor3 from enum import Enum, auto import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * +from dryvr_plus_plus.plotter.plotter2D import * class LaneObjectMode(Enum): diff --git a/demo/demo4.py b/demo/demo4.py index 12ae25b342739dee5e7da5d447266482f8d0174a..576a7cfc500d924df38caeab8bdae16d2bc4352e 100644 --- a/demo/demo4.py +++ b/demo/demo4.py @@ -5,9 +5,9 @@ from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMa from dryvr_plus_plus.plotter.plotter2D import * from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor3 from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor + from enum import Enum, auto import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * class LaneObjectMode(Enum): diff --git a/demo/demo5.py b/demo/demo5.py index 8aeb6a88951d7b0e98ee5798775e76a24047fd94..77bc114cfe335f4b088c995ab56299f06c0913ba 100644 --- a/demo/demo5.py +++ b/demo/demo5.py @@ -6,7 +6,7 @@ from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor3 from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor from enum import Enum, auto import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * +from dryvr_plus_plus.plotter.plotter2D import * class LaneObjectMode(Enum): diff --git a/demo/demo6.py b/demo/demo6.py index ef0146ede1890582cb3ffb97ca8c3c0cbb846b22..19889aded1f1ad4ce97d49da8a2bc25b29355f53 100644 --- a/demo/demo6.py +++ b/demo/demo6.py @@ -8,7 +8,6 @@ from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor from enum import Enum, auto import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * class LaneObjectMode(Enum): diff --git a/demo/demo7.py b/demo/demo7.py index 52efa2e1391ee518fd3cb00675923e935a970394..cd2a30cb4378b7fb25cc7e71b001fc953f2d4c55 100644 --- a/demo/demo7.py +++ b/demo/demo7.py @@ -10,7 +10,6 @@ from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor from enum import Enum, auto import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * class LaneObjectMode(Enum): diff --git a/demo/demo8.py b/demo/demo8.py index b33ca221724137e95205e9de492d758bb997c6c2..73a8ca4f280d4459844074d21dc31e1dc340c44e 100644 --- a/demo/demo8.py +++ b/demo/demo8.py @@ -2,13 +2,11 @@ from dryvr_plus_plus.example.example_agent.car_agent import CarAgent, NPCAgent from dryvr_plus_plus.example.example_agent.sign_agent import SignAgent from dryvr_plus_plus.scene_verifier.scenario.scenario import Scenario from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMap3, SimpleMap5, SimpleMap6 -from dryvr_plus_plus.plotter.plotter2D import * from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor3 +from dryvr_plus_plus.plotter.plotter2D import * from enum import Enum, auto import plotly.graph_objects as go -from dryvr_plus_plus.plotter.plotter2D_new import * - class LaneObjectMode(Enum): Vehicle = auto() diff --git a/demo/example_two_car_sign_lane_switch.py b/demo/example_two_car_sign_lane_switch.py index 64524b310cb1b90615dae80d0b5878298889e15f..f56a1e3fcca96b521a61761f23443ca1717a0700 100644 --- a/demo/example_two_car_sign_lane_switch.py +++ b/demo/example_two_car_sign_lane_switch.py @@ -1,13 +1,13 @@ -import matplotlib.pyplot as plt from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor2 -from dryvr_plus_plus.plotter.plotter2D import plot_reachtube_tree, plot_simulation_tree, generate_simulation_anime, plot_map from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap3 from dryvr_plus_plus.scene_verifier.scenario.scenario import Scenario from dryvr_plus_plus.example.example_agent.sign_agent import SignAgent from dryvr_plus_plus.example.example_agent.car_agent import CarAgent +from dryvr_plus_plus.plotter.plotter2D import * + from enum import Enum, auto import copy - +import plotly.graph_objects as go class LaneObjectMode(Enum): Vehicle = auto() @@ -104,15 +104,10 @@ if __name__ == "__main__": ] ) # simulator = Simulator() - traces = scenario.simulate(40) + traces = scenario.simulate(40,0.05) # traces = scenario.verify(40) - fig = plt.figure() - fig = plot_map(SimpleMap3(), 'g', fig) - # fig = plot_simulation_tree(traces, 'car1', 1, [2], 'b', fig) - # fig = plot_simulation_tree(traces, 'car2', 1, [2], 'r', fig) - fig = plot_reachtube_tree(traces, 'car1', 1, [2], 'b', fig) - fig = plot_reachtube_tree(traces, 'car2', 1, [2], 'r', fig) - - # generate_simulation_anime(traces, SimpleMap3(), fig) - plt.show() + fig = go.Figure() + fig = simulation_anime(traces, None, fig, 1, + 2, 'lines', 'trace', print_dim_list=[1, 2]) + fig.show() diff --git a/demo/plot2.py b/demo/plot2.py deleted file mode 100644 index cf6115a0db987e7baa36f947e222b713ac35f7b2..0000000000000000000000000000000000000000 --- a/demo/plot2.py +++ /dev/null @@ -1,142 +0,0 @@ -from matplotlib import markers -import plotly.graph_objects as go - -import pandas as pd - -url = "https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv" -dataset = pd.read_csv(url) - -years = ["1952", "1962", "1967", "1972", "1977", "1982", "1987", "1992", "1997", "2002", - "2007"] - -# make list of continents -continents = [] -for continent in dataset["continent"]: - if continent not in continents: - continents.append(continent) -# make figure -fig_dict = { - "data": [], - "layout": {}, - "frames": [] -} - -# fill in most of layout -fig_dict["layout"]["xaxis"] = {"range": [30, 85], "title": "Life Expectancy"} -fig_dict["layout"]["yaxis"] = {"title": "GDP per Capita", "type": "log"} -fig_dict["layout"]["hovermode"] = "closest" -fig_dict["layout"]["updatemenus"] = [ - { - "buttons": [ - { - "args": [None, {"frame": {"duration": 500, "redraw": False}, - "fromcurrent": True, "transition": {"duration": 300, - "easing": "quadratic-in-out"}}], - "label": "Play", - "method": "animate" - }, - { - "args": [[None], {"frame": {"duration": 0, "redraw": False}, - "mode": "immediate", - "transition": {"duration": 0}}], - "label": "Pause", - "method": "animate" - } - ], - "direction": "left", - "pad": {"r": 10, "t": 87}, - "showactive": False, - "type": "buttons", - "x": 0.1, - "xanchor": "right", - "y": 0, - "yanchor": "top" - } -] - -sliders_dict = { - "active": 0, - "yanchor": "top", - "xanchor": "left", - "currentvalue": { - "font": {"size": 20}, - "prefix": "Year:", - "visible": True, - "xanchor": "right" - }, - "transition": {"duration": 300, "easing": "cubic-in-out"}, - "pad": {"b": 10, "t": 50}, - "len": 0.9, - "x": 0.1, - "y": 0, - "steps": [] -} - -# make data -year = 1952 -# for continent in continents: -continent = continents[2] -dataset_by_year = dataset[dataset["year"] == year] -dataset_by_year_and_cont = dataset_by_year[ - dataset_by_year["continent"] == continent] - -data_dict = { - "x": list(dataset_by_year_and_cont["lifeExp"]), - "y": list(dataset_by_year_and_cont["gdpPercap"]), - "mode": "markers", - "text": list(dataset_by_year_and_cont["country"]), - "marker": { - "sizemode": "area", - "sizeref": 200000, - "size": list(dataset_by_year_and_cont["pop"]), - "gradient": dict(type='none', color='#000000'), - # "symbol": 'diamond-wide' - }, - "name": continent -} -fig_dict["data"].append(data_dict) - -# make frames -for year in years: - frame = {"data": [], "name": str(year)} - # for continent in continents: - continent = continents[2] - dataset_by_year = dataset[dataset["year"] == int(year)] - dataset_by_year_and_cont = dataset_by_year[ - dataset_by_year["continent"] == continent] - - data_dict = { - "x": list(dataset_by_year_and_cont["lifeExp"]), - "y": list(dataset_by_year_and_cont["gdpPercap"]), - "mode": "markers", - "text": list(dataset_by_year_and_cont["country"]), - "marker": { - "sizemode": "area", - "sizeref": 200000, - "size": list(dataset_by_year_and_cont["pop"]), - "gradient": dict(type='none', color='#000000'), - # "symbol": 'diamond-wide' - - }, - "name": continent - } - frame["data"].append(data_dict) - - fig_dict["frames"].append(frame) - slider_step = {"args": [ - [year], - {"frame": {"duration": 300, "redraw": False}, - "mode": "immediate", - "transition": {"duration": 300}} - ], - "label": year, - "method": "animate"} - sliders_dict["steps"].append(slider_step) - - -fig_dict["layout"]["sliders"] = [sliders_dict] - -fig = go.Figure(fig_dict) -# .update_traces(marker={"gradient": dict(type='radial')}) - -fig.show() diff --git a/demo/plot_test.py b/demo/plot_test.py deleted file mode 100644 index 83bedd06d50750323deaa0716b8113b3bdd10023..0000000000000000000000000000000000000000 --- a/demo/plot_test.py +++ /dev/null @@ -1,164 +0,0 @@ -from turtle import color -import plotly.graph_objects as go -import numpy as np - - -x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -x_rev = x[::-1] -x2 = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20] -x2_rev = x2[::-1] - - -# Line 1 -y1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -y1_upper = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] -y1_lower = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -y1_lower = y1_lower[::-1] - -# Line 2 -y2 = [5, 2.5, 5, 7.5, 5, 2.5, 7.5, 4.5, 5.5, 5] -y2_upper = [5.5, 3, 5.5, 8, 6, 3, 8, 5, 6, 5.5] -y2_lower = [4.5, 2, 4.4, 7, 4, 2, 7, 4, 5, 4.75] -y2_lower = y2_lower[::-1] - -# Line 3 -y3 = [10, 8, 6, 4, 2, 0, 2, 4, 2, 0] -y3_upper = [11, 9, 7, 5, 3, 1, 3, 5, 3, 1] -y3_lower = [9, 7, 5, 3, 1, -.5, 1, 3, 1, -1] -y3_lower = y3_lower[::-1] - - -fig = go.Figure() - -# fig.add_trace(go.Scatter( -# x=x+x_rev + x2+x2_rev, -# y=y1_upper+y1_lower+y1_upper+y1_lower, -# fill='toself', -# marker=dict( -# symbol='square', -# size=16, -# cmax=39, -# cmin=0, -# color='rgb(0,100,80)', -# colorbar=dict( -# title="Colorbar" -# ), -# colorscale="Viridis" -# ), -# # fillcolor='rgba(0,100,80,0.2)', -# # line_color='rgba(255,255,255,0)', -# showlegend=False, -# name='Fair', -# mode="markers" -# )) -# fig.add_trace(go.Scatter( -# x=[1, 2, 2, 1, 2, 3, 3, 2], -# y=[1, 1, 2, 2, 3, 3, 4, 4], -# fill='toself', -# marker=dict( -# symbol='square', -# size=16, -# cmax=3, -# cmin=0, -# color=[1, 2], -# colorbar=dict( -# title="Colorbar" -# ), -# colorscale="Viridis" -# ), -# # fillcolor='rgba(0,100,80,0.2)', -# # line_color='rgba(255,255,255,0)', -# showlegend=False, -# name='Fair', -# mode="markers" -# )) -start = [0, 0, 255, 0.5] -end = [255, 0, 0, 0.5] -rgb = [0, 0, 255, 0.5] -pot = 4 -for i in range(len(rgb)-1): - rgb[i] = rgb[i] + (pot-0)/(4-0)*(end[i]-start[i]) -print(rgb) -fig.add_trace(go.Scatter( - x=[1, 2, 2, 1], - y=[1, 1, 2, 2], - fill='toself', - marker=dict( - symbol='square', - size=16, - cmax=4, - cmin=0, - # color=[3, 3, 3, 3], - colorbar=dict( - title="Colorbar" - ), - colorscale=[[0, 'rgba(0,0,255,0.5)'], [1, 'rgba(255,0,0,0.5)']] - ), - - fillcolor='rgba'+str(tuple(rgb)), - # fillcolor='rgba(0,100,80,0.2)', - # line_color='rgba(255,255,255,0)', - showlegend=False, - name='Fair', - mode="markers" -)) -# for i in range(10): -# fig.add_trace(go.Scatter( -# x=x+x_rev, -# y=y3_upper+y3_lower, -# fill='toself', -# marker=dict( -# symbol='square', -# size=16, -# cmax=39, -# cmin=0, -# color='rgb(0,100,80)', -# colorbar=dict( -# title="Colorbar" -# ), -# colorscale="Viridis" -# ), -# # fillcolor='rgba(0,100,80,0.2)', -# # line_color='rgba(255,255,255,0)', -# showlegend=False, -# name='Fair', -# mode="markers" -# )) -# fig.add_trace(go.Scatter( -# x=x+x_rev, -# y=y2_upper+y2_lower, -# fill='toself', -# fillcolor='rgba(0,176,246,0.2)', -# line_color='rgba(255,255,255,0)', -# name='Premium', -# showlegend=False, -# )) -# fig.add_trace(go.Scatter( -# x=x+x_rev, -# y=y3_upper+y3_lower, -# fill='toself', -# fillcolor='rgba(231,107,243,0.2)', -# line_color='rgba(255,255,255,0)', -# showlegend=False, -# name='Ideal', -# )) -# fig.add_trace(go.Scatter( -# x=x, y=y1, -# line_color='rgb(0,100,80)', -# name='Fair', -# )) -# fig.add_trace(go.Scatter( -# x=x, y=y2, -# line_color='rgb(0,176,246)', -# name='Premium', -# )) -# fig.add_trace(go.Scatter( -# x=x, y=y3, -# line_color='rgb(231,107,243)', -# name='Ideal', -# )) - -# fig.update_traces(mode='lines') -fig.show() -# print(x+x_rev) -# print(y1_upper+y1_lower) diff --git a/demo/plot_test1.py b/demo/plot_test1.py deleted file mode 100644 index 3ba2de2619df0f8ab8f132f866a584f737bd6822..0000000000000000000000000000000000000000 --- a/demo/plot_test1.py +++ /dev/null @@ -1,23 +0,0 @@ -import plotly.graph_objects as go -import numpy as np - -fig = go.Figure() -values = [1, 2, 3] -fig.add_trace(go.Scatter( - x=values, - y=values, - marker=dict( - symbol='square', - size=16, - cmax=39, - cmin=0, - color=values, - colorbar=dict( - title="Colorbar" - ), - colorscale="Viridis" - ), - # marker_symbol='square', marker_line_color="midnightblue", marker_color="lightskyblue", - # marker_line_width=2, marker_size=15, - mode="markers")) -fig.show() diff --git a/dist/dryvr_plus_plus-0.1-py3.8.egg b/dist/dryvr_plus_plus-0.1-py3.8.egg deleted file mode 100644 index cdd7c8753229a16431604862518b4f6f9d13a03d..0000000000000000000000000000000000000000 Binary files a/dist/dryvr_plus_plus-0.1-py3.8.egg and /dev/null differ diff --git a/dryvr_plus_plus/plotter/plotter2D.py b/dryvr_plus_plus/plotter/plotter2D.py index 8dc9f5e644c22a97adee89d0cc1902050257660d..0f8cd26c781efb5ef3b81bf408f7428f802117fa 100644 --- a/dryvr_plus_plus/plotter/plotter2D.py +++ b/dryvr_plus_plus/plotter/plotter2D.py @@ -3,113 +3,73 @@ This file consist main plotter code for DryVR reachtube output """ from __future__ import annotations -from audioop import reverse -# from curses import start_color -from re import A -import matplotlib.patches as patches -import matplotlib.pyplot as plt import numpy as np from math import pi import plotly.graph_objects as go -from typing import List -from PIL import Image, ImageDraw -import io +from typing import List, Tuple import copy -import operator -from collections import OrderedDict - -from torch import layout -from dryvr_plus_plus.scene_verifier.analysis.analysis_tree_node import AnalysisTreeNode - -colors = ['red', 'green', 'blue', 'yellow', 'black'] - -def plotly_plot(data, - x_dim: int = 0, - y_dim_list: List[int] = [1], - color='blue', - fig=None, - x_lim=None, - y_lim=None - ): - if fig is None: - fig = plt.figure() - - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = float('inf'), -float('inf') - for rect in data: - lb = rect[0] - ub = rect[1] - for y_dim in y_dim_list: - fig.add_shape(type="rect", - x0=lb[x_dim], y0=lb[y_dim], x1=ub[x_dim], y1=ub[y_dim], - line=dict(color=color), - fillcolor=color - ) - # rect_patch = patches.Rectangle( - # (lb[x_dim], lb[y_dim]), ub[x_dim]-lb[x_dim], ub[y_dim]-lb[y_dim], color=color) - # ax.add_patch(rect_patch) - x_min = min(lb[x_dim], x_min) - y_min = min(lb[y_dim], y_min) - x_max = max(ub[x_dim], x_max) - y_max = max(ub[y_dim], y_max) - fig.update_shapes(dict(xref='x', yref='y')) - # ax.set_xlim([x_min-1, x_max+1]) - # ax.set_ylim([y_min-1, y_max+1]) - # fig.update_xaxes(range=[x_min-1, x_max+1], showgrid=False) - # fig.update_yaxes(range=[y_min-1, y_max+1]) - return fig, (x_min, x_max), (y_min, y_max) - -def plot( - data, - x_dim: int = 0, - y_dim_list: List[int] = [1], - color='b', - fig=None, - x_lim=None, - y_lim=None -): - if fig is None: - fig = plt.figure() - - ax = fig.gca() - if x_lim is None: - x_lim = ax.get_xlim() - if y_lim is None: - y_lim = ax.get_ylim() - - x_min, x_max = x_lim - y_min, y_max = y_lim - for rect in data: - lb = rect[0] - ub = rect[1] - for y_dim in y_dim_list: - rect_patch = patches.Rectangle( - (lb[x_dim], lb[y_dim]), ub[x_dim]-lb[x_dim], ub[y_dim]-lb[y_dim], color=color) - ax.add_patch(rect_patch) - x_min = min(lb[x_dim], x_min) - y_min = min(lb[y_dim], y_min) - x_max = max(ub[x_dim], x_max) - y_max = max(ub[y_dim], y_max) - - ax.set_xlim([x_min-1, x_max+1]) - ax.set_ylim([y_min-1, y_max+1]) - return fig, (x_min, x_max), (y_min, y_max) +# from dryvr_plus_plus.scene_verifier.analysis.analysis_tree_node import AnalysisTreeNode + +colors = [['#CC0000', '#FF0000', '#FF3333', '#FF6666', '#FF9999'], + ['#CC6600', '#FF8000', '#FF9933', '#FFB266', '#FFCC99'], + ['#CCCC00', '#FFFF00', '#FFFF33', '#FFFF66', '#FFFF99'], + ['#66CC00', '#80FF00', '#99FF33', '#B2FF66', '#CCFF99'], + ['#00CC00', '#00FF00', '#33FF33', '#66FF66', '#99FF99'], + ['#00CC66', '#00FF80', '#33FF99', '#66FFB2', '#99FFCC'], + ['#00CCCC', '#00FFFF', '#33FFFF', '#66FFFF', '#99FFFF'], + ['#0066CC', '#0080FF', '#3399FF', '#66B2FF', '#99CCFF'], + ['#0000CC', '#0000FF', '#3333FF', '#6666FF', '#9999FF'], + ['#6600CC', '#7F00FF', '#9933FF', '#B266FF', '#CC99FF'], + ['#CC00CC', '#FF00FF', '#FF33FF', '#FF66FF', '#FF99FF'], + ['#CC0066', '#FF007F', '#FF3399', '#FF66B2', '#FF99CC'] + ] +scheme_dict = {'red': 0, 'orange': 1, 'yellow': 2, 'yellowgreen': 3, 'lime': 4, + 'springgreen': 5, 'cyan': 6, 'cyanblue': 7, 'blue': 8, 'purple': 9, 'magenta': 10, 'pink': 11} +color_cnt = 0 +text_size = 8 +scale_factor = 0.25 +mode_point_color = 'rgba(0,0,0,0.5)' +mode_text_color = 'black' +duration = 10 + + +"""These 5 Functions below are high-level functions and are recommended to use.""" +""" +API +These 5 functions share the same API. + +- root: the root node of the trace, should be the return value of Scenario.verify() or Scenario.simulate(). +- map: the map of the scenario, templates are in dryvr_plus_plus.example.example_map.simple_map2.py. +- fig: the object of the figure, its type should be plotly.graph_objects.Figure(). +- x_dim: the dimension of x coordinate in the trace list of every time step. The default value is 1. +- y_dim: the dimension of y coordinate in the trace list of every time step. The default value is 2. +- map_type the way to draw the map. It should be 'lines' or 'fill' or 'detailed'. The default value is 'lines'. +-- For the 'lines' mode, map is only drawn by margins of lanes. +-- For the 'fill' mode, the lanes will be filled with semitransparent colors. +-- For the 'detailed' mode, the lanes will be filled some colors according to the speed limits of lanes(if the information is given). + Otherwise, it is the same as the 'lines' mode. +- scale_type the way to scale the coordinate axises. It should be 'trace' or 'map'. The default value is 'trace'. +-- For the 'trace' mode, the traces will be in the center of the plot with an appropriate scale. +-- For the 'map' mode, the map will be in the center of the plot with an appropriate scale. +- print_dim_list the list containing the dimensions of data which will be shown directly or indirectly when the mouse hovers on the point. + The default value is None. And then all dimensions will be shown. +""" -def generate_reachtube_anime(root, map=None, fig=None): - # make figure - fig_dict = { - "data": [], - "layout": {}, - "frames": [] - } - # fig = plot_map(map, 'g', fig) +def reachtube_anime(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim: int = 2, map_type='lines', scale_type='trace', print_dim_list=None): + """It gives the animation of the verfication.""" + agent_list = list(root.agent.keys()) timed_point_dict = {} stack = [root] x_min, x_max = float('inf'), -float('inf') y_min, y_max = float('inf'), -float('inf') - print("reachtude") - end_time = 0 + # input check + num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1] + check_dim(num_dim, x_dim, y_dim, print_dim_list) + if print_dim_list is None: + print_dim_list = range(0, num_dim) + scheme_list = list(scheme_dict.keys()) + while stack != []: node = stack.pop() traces = node.trace @@ -117,27 +77,13 @@ def generate_reachtube_anime(root, map=None, fig=None): trace = np.array(traces[agent_id]) if trace[0][0] > 0: trace = trace[4:] - # print(trace) - end_time = trace[-1][0] - for i in range(0, len(trace), 2): - x_min = min(x_min, trace[i][1]) - x_max = max(x_max, trace[i][1]) - y_min = min(y_min, trace[i][2]) - y_max = max(y_max, trace[i][2]) - # if round(trace[i][0], 2) not in timed_point_dict: - # timed_point_dict[round(trace[i][0], 2)] = [ - # trace[i][1:].tolist()] - # else: - # init = False - # for record in timed_point_dict[round(trace[i][0], 2)]: - # if record == trace[i][1:].tolist(): - # init = True - # break - # if init == False: - # timed_point_dict[round(trace[i][0], 2)].append( - # trace[i][1:].tolist()) + for i in range(0, len(trace)-1, 2): + x_min = min(x_min, trace[i][x_dim]) + x_max = max(x_max, trace[i][x_dim]) + y_min = min(y_min, trace[i][y_dim]) + y_max = max(y_max, trace[i][y_dim]) time_point = round(trace[i][0], 2) - rect = [trace[i][1:].tolist(), trace[i+1][1:].tolist()] + rect = [trace[i][0:].tolist(), trace[i+1][0:].tolist()] if time_point not in timed_point_dict: timed_point_dict[time_point] = {agent_id: [rect]} else: @@ -147,796 +93,817 @@ def generate_reachtube_anime(root, map=None, fig=None): timed_point_dict[time_point][agent_id] = [rect] stack += node.child - # fill in most of layout - # print(end_time) - duration = int(100/end_time) - fig_dict["layout"]["xaxis"] = { - "range": [(x_min-10), (x_max+10)], - "title": "x position"} - fig_dict["layout"]["yaxis"] = { - "range": [(y_min-2), (y_max+2)], - "title": "y position"} - fig_dict["layout"]["hovermode"] = "closest" - fig_dict["layout"]["updatemenus"] = [ - { - "buttons": [ - { - "args": [None, {"frame": {"duration": duration, "redraw": False}, - "fromcurrent": True, "transition": {"duration": duration, - "easing": "quadratic-in-out"}}], - "label": "Play", - "method": "animate" - }, - { - "args": [[None], {"frame": {"duration": 0, "redraw": False}, - "mode": "immediate", - "transition": {"duration": 0}}], - "label": "Pause", - "method": "animate" - } - ], - "direction": "left", - "pad": {"r": 10, "t": 87}, - "showactive": False, - "type": "buttons", - "x": 0.1, - "xanchor": "right", - "y": 0, - "yanchor": "top" - } - ] - sliders_dict = { - "active": 0, - "yanchor": "top", - "xanchor": "left", - "currentvalue": { - "font": {"size": 20}, - "prefix": "time:", - "visible": True, - "xanchor": "right" - }, - # "method": "update", - "transition": {"duration": duration, "easing": "cubic-in-out"}, - "pad": {"b": 10, "t": 50}, - "len": 0.9, - "x": 0.1, - "y": 0, - "steps": [] - } - # make data - agent_dict = timed_point_dict[0] # {agent1:[rect1,..], ...} - x_list = [] - y_list = [] - text_list = [] - for agent_id, rect_list in agent_dict.items(): - for rect in rect_list: - # trace = list(data.values())[0] - print(rect) - x_list.append((rect[0][0]+rect[1][0])/2) - y_list.append((rect[0][1]+rect[1][1])/2) - text_list.append( - ('{:.2f}'.format((rect[0][2]+rect[1][2])/pi*90), '{:.3f}'.format(rect[0][3]+rect[1][3]))) - # data_dict = { - # "x": x_list, - # "y": y_list, - # "mode": "markers + text", - # "text": text_list, - # "textposition": "bottom center", - # # "marker": { - # # "sizemode": "area", - # # "sizeref": 200000, - # # "size": 2 - # # }, - # "name": "Current Position" - # } - # fig_dict["data"].append(data_dict) - - # make frames + fig_dict, sliders_dict = create_anime_dict(duration) for time_point in timed_point_dict: frame = {"data": [], "layout": { "annotations": [], "shapes": []}, "name": str(time_point)} agent_dict = timed_point_dict[time_point] - trace_x = [] - trace_y = [] - trace_theta = [] - trace_v = [] for agent_id, rect_list in agent_dict.items(): for rect in rect_list: - trace_x.append((rect[0][0]+rect[1][0])/2) - trace_y.append((rect[0][1]+rect[1][1])/2) - trace_theta.append((rect[0][2]+rect[1][2])/2) - trace_v.append((rect[0][3]+rect[1][3])/2) shape_dict = { "type": 'rect', - "x0": rect[0][0], - "y0": rect[0][1], - "x1": rect[1][0], - "y1": rect[1][1], - "fillcolor": 'rgba(255,255,255,0.5)', + "x0": rect[0][x_dim], + "y0": rect[0][y_dim], + "x1": rect[1][x_dim], + "y1": rect[1][y_dim], + "fillcolor": 'rgba(0,0,0,0.5)', "line": dict(color='rgba(255,255,255,0)'), + "visible": True } frame["layout"]["shapes"].append(shape_dict) - # data_dict = { - # "x": trace_x, - # "y": trace_y, - # "mode": "markers + text", - # "text": [('{:.2f}'.format(trace_theta[i]/pi*180), '{:.3f}'.format(trace_v[i])) for i in range(len(trace_theta))], - # "textposition": "bottom center", - # # "marker": { - # # "sizemode": "area", - # # "sizeref": 200000, - # # "size": 2 - # # }, - # "name": "current position" - # } - # frame["data"].append(data_dict) - # print(trace_x) + fig_dict["frames"].append(frame) slider_step = {"args": [ - [time_point], + ['{:.2f}'.format(time_point)], {"frame": {"duration": duration, "redraw": False}, "mode": "immediate", "transition": {"duration": duration}} ], - "label": time_point, + "label": '{:.2f}'.format(time_point), "method": "animate"} sliders_dict["steps"].append(slider_step) - # print(len(frame["layout"]["annotations"])) fig_dict["layout"]["sliders"] = [sliders_dict] fig = go.Figure(fig_dict) - # fig = plotly_map(map, 'g', fig) - i = 1 - for agent_id in traces: - fig = plotly_reachtube_tree_v2(root, agent_id, 1, [2], i, fig) - i += 2 + fig = draw_map(map=map, fig=fig, fill_type=map_type) + i = 0 + for agent_id in agent_list: + fig = reachtube_tree_single( + root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list) + i = (i+1) % 12 + if scale_type == 'trace': + queue = [root] + x_min, x_max = float('inf'), -float('inf') + y_min, y_max = float('inf'), -float('inf') + i = 0 + queue = [root] + previous_mode = {} + for agent_id in root.mode: + previous_mode[agent_id] = [] + text_pos = 'middle center' + while queue != []: + node = queue.pop(0) + traces = node.trace + for agent_id in traces: + trace = np.array(traces[agent_id]) + if scale_type == 'trace': + x_min = min(x_min, min(trace[:, x_dim])) + x_max = max(x_max, max(trace[:, x_dim])) + y_min = min(y_min, min(trace[:, y_dim])) + y_max = max(y_max, max(trace[:, y_dim])) + if previous_mode[agent_id] != node.mode[agent_id]: + text_pos, text = get_text_pos(node.mode[agent_id][0]) + x0 = trace[0, x_dim] + x1 = trace[1, x_dim] + y0 = trace[0, y_dim] + y1 = trace[1, y_dim] + mode_point_color = colors[agent_list.index(agent_id) % 12][0] + fig.add_trace(go.Scatter(x=[(x0+x1)/2], y=[(y0+y1)/2], + mode='markers+text', + line_color=mode_point_color, + text=str(agent_id)+': ' + text, + textposition=text_pos, + opacity=0.5, + textfont=dict( + size=text_size, + color=mode_text_color), + showlegend=False, + )) + previous_mode[agent_id] = node.mode[agent_id] + queue += node.child + if scale_type == 'trace': + fig.update_xaxes( + range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) + fig.update_yaxes( + range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) + return fig + +def reachtube_tree(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None): + """It statically shows all the traces of the verfication.""" + fig = draw_map(map=map, fig=fig, fill_type=map_type) + agent_list = list(root.agent.keys()) + # input check + num_dim = np.array(root.trace[agent_list[0]]).shape[1] + check_dim(num_dim, x_dim, y_dim, print_dim_list) + if print_dim_list is None: + print_dim_list = range(0, num_dim) + + scheme_list = list(scheme_dict.keys()) + i = 0 + for agent_id in agent_list: + fig = reachtube_tree_single( + root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list) + i = (i+1) % 12 + if scale_type == 'trace': + queue = [root] + x_min, x_max = float('inf'), -float('inf') + y_min, y_max = float('inf'), -float('inf') + i = 0 + queue = [root] + previous_mode = {} + for agent_id in root.mode: + previous_mode[agent_id] = [] + text_pos = 'middle center' + while queue != []: + node = queue.pop(0) + traces = node.trace + i = 0 + for agent_id in traces: + trace = np.array(traces[agent_id]) + if scale_type == 'trace': + x_min = min(x_min, min(trace[:, x_dim])) + x_max = max(x_max, max(trace[:, x_dim])) + y_min = min(y_min, min(trace[:, y_dim])) + y_max = max(y_max, max(trace[:, y_dim])) + i = agent_list.index(agent_id) + if previous_mode[agent_id] != node.mode[agent_id]: + text_pos, text = get_text_pos(node.mode[agent_id][0]) + mode_point_color = colors[agent_list.index(agent_id) % 12][0] + fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]], + mode='markers+text', + line_color=mode_point_color, + opacity=0.5, + text=str(agent_id)+': ' + text, + textposition=text_pos, + textfont=dict( + size=text_size, + color=mode_text_color), + showlegend=False, + )) + previous_mode[agent_id] = node.mode[agent_id] + queue += node.child + if scale_type == 'trace': + fig.update_xaxes( + range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) + fig.update_yaxes( + range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) return fig -def plotly_reachtube_tree(root, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color='blue', fig=None, x_lim=None, y_lim=None): - if fig is None: - fig = go.Figure() +def simulation_tree(root, map=None, fig=None, x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None): + """It statically shows all the traces of the simulation.""" + fig = draw_map(map=map, fig=fig, fill_type=map_type) + agent_list = list(root.agent.keys()) + # input check + num_dim = np.array(root.trace[agent_list[0]]).shape[1] + check_dim(num_dim, x_dim, y_dim, print_dim_list) + if print_dim_list is None: + print_dim_list = range(0, num_dim) - # ax = fig.gca() - # if x_lim is None: - # x_lim = ax.get_xlim() - # if y_lim is None: - # y_lim = ax.get_ylim() + scheme_list = list(scheme_dict.keys()) + i = 0 + for agent_id in agent_list: + fig = simulation_tree_single( + root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list) + i = (i+1) % 12 + if scale_type == 'trace': + queue = [root] + x_min, x_max = float('inf'), -float('inf') + y_min, y_max = float('inf'), -float('inf') + i = 0 + queue = [root] + previous_mode = {} + for agent_id in root.mode: + previous_mode[agent_id] = [] + text_pos = 'middle center' + while queue != []: + node = queue.pop(0) + traces = node.trace + i = 0 + for agent_id in traces: + trace = np.array(traces[agent_id]) + if scale_type == 'trace': + x_min = min(x_min, min(trace[:, x_dim])) + x_max = max(x_max, max(trace[:, x_dim])) + y_min = min(y_min, min(trace[:, y_dim])) + y_max = max(y_max, max(trace[:, y_dim])) + i = agent_list.index(agent_id) + mode_point_color = colors[agent_list.index(agent_id) % 12][0] + if previous_mode[agent_id] != node.mode[agent_id]: + text_pos, text = get_text_pos(node.mode[agent_id][0]) + fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]], + mode='markers+text', + line_color=mode_point_color, + opacity=0.5, + text=str(agent_id)+': ' + text, + textposition=text_pos, + textfont=dict( + size=text_size, + color=mode_text_color + ), + showlegend=False, + )) + previous_mode[agent_id] = node.mode[agent_id] + queue += node.child + if scale_type == 'trace': + fig.update_xaxes( + range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) + fig.update_yaxes( + range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) + fig.update_xaxes(title='x') + fig.update_yaxes(title='y') + fig.update_layout(legend_title_text='Agent list') + return fig + +def simulation_anime(root, map=None, fig=None, x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None): + """It gives the animation of the simulation without trail but is faster.""" + timed_point_dict = {} + stack = [root] + x_min, x_max = float('inf'), -float('inf') + y_min, y_max = float('inf'), -float('inf') + # input check + num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1] + check_dim(num_dim, x_dim, y_dim, print_dim_list) + if print_dim_list is None: + print_dim_list = range(0, num_dim) + agent_list = list(root.agent.keys()) + while stack != []: + node = stack.pop() + traces = node.trace + for agent_id in traces: + trace = np.array(traces[agent_id]) + for i in range(len(trace)): + x_min = min(x_min, trace[i][x_dim]) + x_max = max(x_max, trace[i][x_dim]) + y_min = min(y_min, trace[i][y_dim]) + y_max = max(y_max, trace[i][y_dim]) + time_point = round(trace[i][0], 2) + tmp_trace = trace[i][0:].tolist() + if time_point not in timed_point_dict: + timed_point_dict[time_point] = {agent_id: [tmp_trace]} + else: + if agent_id not in timed_point_dict[time_point].keys(): + timed_point_dict[time_point][agent_id] = [tmp_trace] + elif tmp_trace not in timed_point_dict[time_point][agent_id]: + timed_point_dict[time_point][agent_id].append( + tmp_trace) + time = round(trace[i][0], 2) + stack += node.child + fig_dict, sliders_dict = create_anime_dict(duration) + # make data + trace_dict = timed_point_dict[0] + for agent_id, trace_list in trace_dict.items(): + color = colors[agent_list.index(agent_id) % 12][1] + x_list = [] + y_list = [] + text_list = [] + branch_cnt = 0 + for trace in trace_list: + x_list.append(trace[x_dim]) + y_list.append(trace[y_dim]) + text_list.append(['{:.2f}'.format(trace[i]) + for i in print_dim_list]) + branch_cnt += 1 + data_dict = { + "x": x_list, + "y": y_list, + "text": text_list, + "mode": "markers + text", + "textfont": dict(size=text_size, color="black"), + "textposition": "bottom center", + "marker": { + "color": color, + }, + "name": agent_id, + "showlegend": True + } + fig_dict["data"].append(data_dict) + # make frames + for time_point in timed_point_dict: + frame = {"data": [], "layout": { + "annotations": []}, "name": '{:.2f}'.format(time_point)} + point_list = timed_point_dict[time_point] + for agent_id, trace_list in point_list.items(): + color = colors[agent_list.index(agent_id) % 12][1] + x_list = [] + y_list = [] + text_list = [] + branch_cnt = 0 + for trace in trace_list: + x_list.append(trace[x_dim]) + y_list.append(trace[y_dim]) + text_list.append(['{:.2f}'.format(trace[i]) + for i in print_dim_list]) + branch_cnt += 1 + data_dict = { + "x": x_list, + "y": y_list, + "text": text_list, + "mode": "markers + text", + "marker": { + "color": color, + }, + "textfont": dict(size=text_size, color="black"), + "textposition": "bottom center", + # "name": "Branch-"+str(branch_cnt), + "name": agent_id, + "showlegend": True + } + frame["data"].append(data_dict) + fig_dict["frames"].append(frame) + slider_step = {"args": [ + ['{:.2f}'.format(time_point)], + {"frame": {"duration": duration, "redraw": True}, + "mode": "immediate", + "transition": {"duration": duration}} + ], + "label": '{:.2f}'.format(time_point), + "method": "animate"} + sliders_dict["steps"].append(slider_step) + + fig_dict["layout"]["sliders"] = [sliders_dict] + + fig = go.Figure(fig_dict) + fig = draw_map(map, 'rgba(0,0,0,1)', fig, map_type) + i = 0 queue = [root] + previous_mode = {} + agent_list = list(root.agent.keys()) + for agent_id in root.mode: + previous_mode[agent_id] = [] + text_pos = 'middle center' while queue != []: node = queue.pop(0) traces = node.trace - trace = traces[agent_id] - # print(trace) - data = [] - for i in range(0, len(trace)-1, 2): - data.append([trace[i], trace[i+1]]) - fig, x_lim, y_lim = plotly_plot( - data, x_dim, y_dim_list, color, fig, x_lim, y_lim) - # print(data) + for agent_id in traces: + trace = np.array(traces[agent_id]) + mode_point_color = colors[agent_list.index(agent_id) % 12][0] + if previous_mode[agent_id] != node.mode[agent_id]: + text_pos, text = get_text_pos(node.mode[agent_id][0]) + fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]], + mode='markers+text', + line_color=mode_point_color, + text=str(agent_id)+': ' + text, + textposition=text_pos, + opacity=0.5, + textfont=dict( + size=text_size, + color=mode_text_color), + showlegend=False, + )) + previous_mode[agent_id] = node.mode[agent_id] queue += node.child + if scale_type == 'trace': + fig.update_xaxes( + range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) + fig.update_yaxes( + range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) + fig.update_layout(legend_title_text='Agent list') + return fig + +def simulation_anime_trail(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None): + """It gives the animation of the simulation with trail.""" + timed_point_dict = {} + stack = [root] + x_min, x_max = float('inf'), -float('inf') + y_min, y_max = float('inf'), -float('inf') + # input check + num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1] + check_dim(num_dim, x_dim, y_dim, print_dim_list) + if print_dim_list is None: + print_dim_list = range(0, num_dim) + + while stack != []: + node = stack.pop() + traces = node.trace + for agent_id in traces: + trace = np.array(traces[agent_id]) + for i in range(len(trace)): + x_min = min(x_min, trace[i][x_dim]) + x_max = max(x_max, trace[i][x_dim]) + y_min = min(y_min, trace[i][y_dim]) + y_max = max(y_max, trace[i][y_dim]) + time_point = round(trace[i][0], 3) + tmp_trace = trace[i][0:].tolist() + if time_point not in timed_point_dict: + timed_point_dict[time_point] = {agent_id: [tmp_trace]} + else: + if agent_id not in timed_point_dict[time_point].keys(): + timed_point_dict[time_point][agent_id] = [tmp_trace] + elif tmp_trace not in timed_point_dict[time_point][agent_id]: + timed_point_dict[time_point][agent_id].append( + tmp_trace) + time = round(trace[i][0], 2) + stack += node.child + fig_dict, sliders_dict = create_anime_dict(duration) + time_list = list(timed_point_dict.keys()) + agent_list = list(root.agent.keys()) + trail_limit = min(10, len(time_list)) + trail_len = trail_limit + opacity_step = 1/trail_len + size_step = 2/trail_len + min_size = 5 + step = 2 + # # make data + trace_dict = timed_point_dict[0] + + for time_point in list(timed_point_dict.keys())[0:int(trail_limit/step)]: + trace_dict = timed_point_dict[time_point] + for agent_id, point_list in trace_dict.items(): + x_list = [] + y_list = [] + text_list = [] + for point in point_list: + x_list.append(point[x_dim]) + y_list.append(point[y_dim]) + text_list.append(['{:.2f}'.format(point[i]) + for i in print_dim_list]) + data_dict = { + "x": x_list, + "y": y_list, + "mode": "markers", + "text": text_list, + "textfont": dict(size=text_size, color="black"), + "visible": False, + "textposition": "bottom center", + "name": agent_id + } + fig_dict["data"].append(data_dict) + + # make frames + for time_point_id in range(trail_limit, len(time_list)): + time_point = time_list[time_point_id] + frame = {"data": [], "layout": { + "annotations": []}, "name": '{:.2f}'.format(time_point)} + for agent_id in agent_list: + color = colors[agent_list.index(agent_id) % 12][1] + for id in range(0, trail_len, step): + tmp_point_list = timed_point_dict[time_list[time_point_id-id]][agent_id] + trace_x = [] + trace_y = [] + text_list = [] + for point in tmp_point_list: + trace_x.append(point[x_dim]) + trace_y.append(point[y_dim]) + text_list.append(['{:.2f}'.format(point[i]) + for i in print_dim_list]) + if id == 0: + data_dict = { + "x": trace_x, + "y": trace_y, + "mode": "markers+text", + "text": text_list, + "textfont": dict(size=text_size, color="black"), + "textposition": "bottom center", + "visible": True, # 'legendonly' + "marker": { + "color": color, + "opacity": opacity_step*(trail_len-id), + "size": min_size + size_step*(trail_len-id) + }, + "name": agent_id, + "showlegend": True + } + else: + data_dict = { + "x": trace_x, + "y": trace_y, + "mode": "markers", + "text": text_list, + "visible": True, # 'legendonly' + "marker": { + "color": color, + "opacity": opacity_step*(trail_len-id), + "size": min_size + size_step*(trail_len-id) + }, + "name": agent_id, + "showlegend": True + } + frame["data"].append(data_dict) + + fig_dict["frames"].append(frame) + slider_step = {"args": [ + ['{:.2f}'.format(time_point)], + {"frame": {"duration": duration, "redraw": False}, + "mode": "immediate", + "transition": {"duration": duration}} + ], + "label": '{:.2f}'.format(time_point), + "method": "animate"} + sliders_dict["steps"].append(slider_step) + + fig_dict["layout"]["sliders"] = [sliders_dict] + + fig = go.Figure(fig_dict) + fig = draw_map(map, 'rgba(0,0,0,1)', fig, map_type) + i = 0 + queue = [root] + previous_mode = {} + agent_list = list(root.agent.keys()) + for agent_id in root.mode: + previous_mode[agent_id] = [] + text_pos = 'middle center' + while queue != []: + node = queue.pop(0) + traces = node.trace + i = 0 + for agent_id in traces: + trace = np.array(traces[agent_id]) + trace_y = trace[:, y_dim].tolist() + trace_x = trace[:, x_dim].tolist() + i = agent_list.index(agent_id) + mode_point_color = colors[agent_list.index(agent_id) % 12][0] + if previous_mode[agent_id] != node.mode[agent_id]: + text_pos, text = get_text_pos(node.mode[agent_id][0]) + fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]], + mode='markers+text', + line_color=mode_point_color, + text=str(agent_id)+': ' + text, + opacity=0.5, + textposition=text_pos, + textfont=dict( + size=text_size, + color=mode_text_color + ), + showlegend=False, + )) + previous_mode[agent_id] = node.mode[agent_id] + queue += node.child + if scale_type == 'trace': + fig.update_xaxes( + range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) + fig.update_yaxes( + range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) + fig.update_layout(legend_title_text='Agent list') return fig -def plotly_reachtube_tree_v2(root, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color=0, fig=None, x_lim=None, y_lim=None): - if fig is None: - fig = go.Figure() +"""Functions below are low-level functions and usually are not called outside this file.""" + - # ax = fig.gca() - # if x_lim is None: - # x_lim = ax.get_xlim() - # if y_lim is None: - # y_lim = ax.get_ylim() - bg_color = ['rgba(31,119,180,1)', 'rgba(255,127,14,0.2)', 'rgba(44,160,44,0.2)', 'rgba(214,39,40,0.2)', 'rgba(148,103,189,0.2)', - 'rgba(140,86,75,0.2)', 'rgba(227,119,194,0.2)', 'rgba(127,127,127,0.2)', 'rgba(188,189,34,0.2)', 'rgba(23,190,207,0.2)'] +def reachtube_tree_single(root, agent_id, fig=go.Figure(), x_dim: int = 1, y_dim: int = 2, color=None, print_dim_list=None): + """It statically shows the verfication traces of one given agent.""" + global color_cnt + if color == None: + color = list(scheme_dict.keys())[color_cnt] + color_cnt = (color_cnt+1) % 12 queue = [root] show_legend = False + fillcolor = colors[scheme_dict[color]][4] while queue != []: node = queue.pop(0) traces = node.trace trace = np.array(traces[agent_id]) - # print(trace[0], trace[1], trace[-2], trace[-1]) max_id = len(trace)-1 - # trace_x = np.zeros(max_id+1) - # trace_x_2 = np.zeros(max_id+1) - # trace_y = np.zeros(max_id+1) - # trace_y_2 = np.zeros(max_id+1) - # for y_dim in y_dim_list: - # for i in range(0, max_id, 2): - # id = int(i/2) - # trace_x[id] = trace[i+1][x_dim] - # trace_x[max_id-id] = trace[i][x_dim] - # trace_x_2[id] = trace[i][x_dim] - # trace_x_2[max_id-id] = trace[i+1][x_dim] - # trace_y[id] = trace[i][y_dim] - # trace_y[max_id-id] = trace[i+1][y_dim] - # fig.add_trace(go.Scatter(x=trace_x, y=trace_y, - # fill='toself', - # fillcolor='blue', - # line_color='rgba(255,255,255,0)', - # showlegend=False)) - # fig.add_trace(go.Scatter(x=trace_x_2, y=trace_y, - # fill='toself', - # fillcolor='red', - # line_color='rgba(255,255,255,0)', - # showlegend=False)) - # fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2], - # mode='lines', - # line_color="black", - # text=[range(0, max_id+1)], - # name='lines', - # showlegend=False)) - trace_x_odd = np.array([trace[i][1] for i in range(0, max_id, 2)]) - trace_x_even = np.array([trace[i][1] for i in range(1, max_id+1, 2)]) - trace_y_odd = np.array([trace[i][2] for i in range(0, max_id, 2)]) - trace_y_even = np.array([trace[i][2] for i in range(1, max_id+1, 2)]) + trace_x_odd = np.array([trace[i][x_dim] for i in range(0, max_id, 2)]) + trace_x_even = np.array([trace[i][x_dim] + for i in range(1, max_id+1, 2)]) + trace_y_odd = np.array([trace[i][y_dim] for i in range(0, max_id, 2)]) + trace_y_even = np.array([trace[i][y_dim] + for i in range(1, max_id+1, 2)]) fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', fill='toself', - fillcolor=bg_color[color], + fillcolor=fillcolor, + opacity=0.5, line_color='rgba(255,255,255,0)', showlegend=show_legend )) fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', fill='toself', - fillcolor=bg_color[color], + fillcolor=fillcolor, + opacity=0.5, line_color='rgba(255,255,255,0)', showlegend=show_legend)) fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', fill='toself', - fillcolor=bg_color[color], + fillcolor=fillcolor, + opacity=0.5, line_color='rgba(255,255,255,0)', showlegend=show_legend )) fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', fill='toself', - fillcolor=bg_color[color], + fillcolor=fillcolor, + opacity=0.5, line_color='rgba(255,255,255,0)', showlegend=show_legend)) - # fig.add_trace(go.Scatter(x=trace_x_odd.tolist(), y=trace_y_odd.tolist(), mode='lines', - # # fill='toself', - # # fillcolor=bg_color[0], - # # line=dict(width=1, dash="solid"), - # line_color=bg_color[0], - # showlegend=True - # )) - # fig.add_trace(go.Scatter(x=trace_x_even.tolist(), y=trace_y_odd.tolist(), mode='lines', - # # fill='toself', - # # fillcolor=bg_color[0], - # # line=dict(width=1, dash="solid"), - # line_color=bg_color[0], - # showlegend=True)) - # fig.add_trace(go.Scatter(x=trace_x_odd.tolist(), y=trace_y_even.tolist(), mode='lines', - # # fill='toself', - # # fillcolor=bg_color[0], - # # line=dict(width=1, dash="solid",shape="spline"), - # line_color=bg_color[0], - # showlegend=True - # )) - # fig.add_trace(go.Scatter(x=trace_x_even.tolist(), y=trace_y_even.tolist(), mode='lines', - # # fill='toself', - # # fillcolor=bg_color[0], - # # line=dict(width=1, dash="solid"), - # line_color=bg_color[0], - # showlegend=True)) - # fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2], - # mode='markers', - # # fill='toself', - # # line=dict(dash="dot"), - # line_color="black", - # text=[range(0, max_id+1)], - # name='lines', - # showlegend=False)) queue += node.child + queue = [root] while queue != []: node = queue.pop(0) traces = node.trace trace = np.array(traces[agent_id]) - # print(trace[0], trace[1], trace[-2], trace[-1]) max_id = len(trace)-1 - # trace_x = np.zeros(max_id+1) - # trace_x_2 = np.zeros(max_id+1) - # trace_y = np.zeros(max_id+1) - # trace_y_2 = np.zeros(max_id+1) - # for y_dim in y_dim_list: - # for i in range(0, max_id, 2): - # id = int(i/2) - # trace_x[id] = trace[i+1][x_dim] - # trace_x[max_id-id] = trace[i][x_dim] - # trace_x_2[id] = trace[i][x_dim] - # trace_x_2[max_id-id] = trace[i+1][x_dim] - # trace_y[id] = trace[i][y_dim] - # trace_y[max_id-id] = trace[i+1][y_dim] - # fig.add_trace(go.Scatter(x=trace_x, y=trace_y, - # fill='toself', - # fillcolor='blue', - # line_color='rgba(255,255,255,0)', - # showlegend=False)) - # fig.add_trace(go.Scatter(x=trace_x_2, y=trace_y, - # fill='toself', - # fillcolor='red', - # line_color='rgba(255,255,255,0)', - # showlegend=False)) - # fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2], - # mode='lines', - # line_color="black", - # text=[range(0, max_id+1)], - # name='lines', - # showlegend=False)) - # trace_x_odd = np.array([trace[i][1] for i in range(0, max_id, 2)]) - # trace_x_even = np.array([trace[i][1] for i in range(1, max_id+1, 2)]) - # trace_y_odd = np.array([trace[i][2] for i in range(0, max_id, 2)]) - # trace_y_even = np.array([trace[i][2] for i in range(1, max_id+1, 2)]) - # fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', - # fill='toself', - # fillcolor=bg_color[0], - # line_color='rgba(255,255,255,0)', - # showlegend=True - # )) - # fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', - # fill='toself', - # fillcolor=bg_color[0], - # line_color='rgba(255,255,255,0)', - # showlegend=True)) - # fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', - # fill='toself', - # fillcolor=bg_color[0], - # line_color='rgba(255,255,255,0)', - # showlegend=True - # )) - # fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', - # fill='toself', - # fillcolor=bg_color[0], - # line_color='rgba(255,255,255,0)', - # showlegend=True)) - # fig.add_trace(go.Scatter(x=trace_x_odd.tolist(), y=trace_y_odd.tolist(), mode='lines', - # # fill='toself', - # # fillcolor=bg_color[0], - # # line=dict(width=1, dash="solid"), - # line_color=bg_color[0], - # showlegend=True - # )) - # fig.add_trace(go.Scatter(x=trace_x_even.tolist(), y=trace_y_odd.tolist(), mode='lines', - # # fill='toself', - # # fillcolor=bg_color[0], - # # line=dict(width=1, dash="solid"), - # line_color=bg_color[0], - # showlegend=True)) - # fig.add_trace(go.Scatter(x=trace_x_odd.tolist(), y=trace_y_even.tolist(), mode='lines', - # # fill='toself', - # # fillcolor=bg_color[0], - # # line=dict(width=1, dash="solid",shape="spline"), - # line_color=bg_color[0], - # showlegend=True - # )) - # fig.add_trace(go.Scatter(x=trace_x_even.tolist(), y=trace_y_even.tolist(), mode='lines', - # # fill='toself', - # # fillcolor=bg_color[0], - # # line=dict(width=1, dash="solid"), - # line_color=bg_color[0], - # showlegend=True)) - fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2], + fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim], mode='markers', - # fill='toself', - # line=dict(dash="dot"), - line_color="black", + text=[ + ['{:.2f}'.format(trace[i, j])for j in print_dim_list] for i in range(0, trace.shape[0])], + line_color=colors[scheme_dict[color]][0], marker={ "sizemode": "area", "sizeref": 200000, "size": 2 }, - text=[range(0, max_id+1)], name='lines', showlegend=False)) queue += node.child - # fig.update_traces(line_dash="dash") return fig -def plot_reachtube_tree(root, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color='b', fig=None, x_lim=None, y_lim=None): - if fig is None: - fig = plt.figure() - - ax = fig.gca() - if x_lim is None: - x_lim = ax.get_xlim() - if y_lim is None: - y_lim = ax.get_ylim() - +def simulation_tree_single(root, agent_id, fig: go.Figure() = go.Figure(), x_dim: int = 1, y_dim: int = 2, color=None, print_dim_list=None): + """It statically shows the simulation traces of one given agent.""" + global color_cnt queue = [root] + color_id = 0 + if color == None: + color = list(scheme_dict.keys())[color_cnt] + color_cnt = (color_cnt+1) % 12 + start_list = [] + end_list = [] + count_dict = {} while queue != []: node = queue.pop(0) traces = node.trace - trace = traces[agent_id] - # print(trace) - data = [] - - for i in range(0, len(trace)-1, 2): - data.append([trace[i], trace[i+1]]) - fig, x_lim, y_lim = plot( - data, x_dim, y_dim_list, color, fig, x_lim, y_lim) - queue += node.child - return fig - -def plot_reachtube_tree_branch(root, agent_id, x_dim: int=0, y_dim_list: List[int]=[1], color='b', fig = None, x_lim = None, y_lim = None): - if fig is None: - fig = plt.figure() - - ax = fig.gca() - if x_lim is None: - x_lim = ax.get_xlim() - if y_lim is None: - y_lim = ax.get_ylim() - - stack = [root] - while stack != []: - node = stack.pop() - traces = node.trace - trace = traces[agent_id] - data = [] - for i in range(0,len(trace),2): - data.append([trace[i], trace[i+1]]) - fig, x_lim, y_lim = plot(data, x_dim, y_dim_list, color, fig, x_lim, y_lim) - - if node.child: - stack += [node.child[0]] - return fig - - -def plotly_map(map, color='b', fig: go.Figure() = None, x_lim=None, y_lim=None): - if fig is None: - fig = go.Figure() - all_x = [] - all_y = [] - all_v = [] - for lane_idx in map.lane_dict: - lane = map.lane_dict[lane_idx] - for lane_seg in lane.segment_list: - if lane_seg.type == 'Straight': - start1 = lane_seg.start + lane_seg.width/2 * lane_seg.direction_lateral - end1 = lane_seg.end + lane_seg.width/2 * lane_seg.direction_lateral - # fig.add_trace(go.Scatter(x=[start1[0], end1[0]], y=[start1[1], end1[1]], - # mode='lines', - # line_color='black', - # showlegend=False, - # # text=theta, - # name='lines')) - start2 = lane_seg.start - lane_seg.width/2 * lane_seg.direction_lateral - end2 = lane_seg.end - lane_seg.width/2 * lane_seg.direction_lateral - # fig.add_trace(go.Scatter(x=[start2[0], end2[0]], y=[start2[1], end2[1]], - # mode='lines', - # line_color='black', - # showlegend=False, - # # text=theta, - # name='lines')) - fig.add_trace(go.Scatter(x=[start1[0], end1[0], end2[0], start2[0]], y=[start1[1], end1[1], end2[1], start2[1]], - mode='lines', - line_color='black', - # fill='toself', - # fillcolor='rgba(255,255,255,0)', - # line_color='rgba(0,0,0,0)', - showlegend=False, - # text=theta, - name='lines')) - # fig = go.Figure().add_heatmap(x=) - seg_x, seg_y, seg_v = lane_seg.get_all_speed() - all_x += seg_x - all_y += seg_y - all_v += seg_v - elif lane_seg.type == "Circular": - phase_array = np.linspace( - start=lane_seg.start_phase, stop=lane_seg.end_phase, num=100) - r1 = lane_seg.radius - lane_seg.width/2 - x = np.cos(phase_array)*r1 + lane_seg.center[0] - y = np.sin(phase_array)*r1 + lane_seg.center[1] - fig.add_trace(go.Scatter(x=x, y=y, - mode='lines', - line_color='black', - showlegend=False, - # text=theta, - name='lines')) - - r2 = lane_seg.radius + lane_seg.width/2 - x = np.cos(phase_array)*r2 + lane_seg.center[0] - y = np.sin(phase_array)*r2 + lane_seg.center[1] - fig.add_trace(go.Scatter(x=x, y=y, - mode='lines', - line_color='black', - showlegend=False, - # text=theta, - name='lines')) - else: - raise ValueError(f'Unknown lane segment type {lane_seg.type}') - start_color = [0, 0, 255, 0.2] - end_color = [255, 0, 0, 0.2] - curr_color = copy.deepcopy(start_color) - max_speed = max(all_v) - min_speed = min(all_v) - - for i in range(len(all_v)): - # print(all_x[i]) - # print(all_y[i]) - # print(all_v[i]) - curr_color = copy.deepcopy(start_color) - for j in range(len(curr_color)-1): - curr_color[j] += (all_v[i]-min_speed)/(max_speed - - min_speed)*(end_color[j]-start_color[j]) - fig.add_trace(go.Scatter(x=all_x[i], y=all_y[i], + if agent_id not in traces.keys(): + return fig + trace = np.array(traces[agent_id]) + start = list(trace[0]) + end = list(trace[-1]) + if (start in start_list) and (end in end_list): + continue + time = tuple([round(start[0], 2), round(end[0], 2)]) + if time in count_dict.keys(): + count_dict[time] += 1 + else: + count_dict[time] = 1 + start_list.append(start) + end_list.append(end) + fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim], mode='lines', - line_color='rgba(0,0,0,0)', - fill='toself', - fillcolor='rgba'+str(tuple(curr_color)), - # marker=dict( - # symbol='square', - # size=16, - # cmax=max_speed, - # cmin=min_speed, - # # color=all_v[i], - # colorbar=dict( - # title="Colorbar" - # ), - # colorscale=[ - # [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]] - # ), - showlegend=False, - )) - fig.add_trace(go.Scatter(x=[0], y=[0], - mode='markers', - # fill='toself', - # fillcolor='rgba'+str(tuple(curr_color)), - marker=dict( - symbol='square', - size=16, - cmax=max_speed, - cmin=min_speed, - color='rgba(0,0,0,0)', - colorbar=dict( - title="Speed Limit" - ), - colorscale=[ - [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]] - ), - showlegend=False, + line_color=colors[scheme_dict[color] + ][color_id], + text=[ + ['{:.2f}'.format(trace[i, j])for j in print_dim_list] for i in range(trace.shape[0])], + legendgroup=agent_id, + legendgrouptitle_text=agent_id, + name=str(round(start[0], 2))+'-'+str(round(end[0], 2)) + + '-'+str(count_dict[time]), + showlegend=True)) + color_id = (color_id+4) % 5 + queue += node.child + fig.update_layout(legend=dict( + groupclick="toggleitem", + itemclick="toggle", + itemdoubleclick="toggleothers" )) - # fig.update_coloraxes(colorbar=dict(title="Colorbar"), colorscale=[ - # [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]]) return fig -def plot_map(map, color='b', fig=None, x_lim=None, y_lim=None): - if fig is None: - fig = plt.figure() - - ax = fig.gca() - if x_lim is None: - x_lim = ax.get_xlim() - if y_lim is None: - y_lim = ax.get_ylim() - +def draw_map(map, color='rgba(0,0,0,1)', fig: go.Figure() = go.Figure(), fill_type='lines'): + """It draws the the map""" + x_min, x_max = float('inf'), -float('inf') + y_min, y_max = float('inf'), -float('inf') + if map is None: + return fig + if fill_type == 'detailed': + speed_dict = map.get_all_speed_limit() + speed_list = list(filter(None, speed_dict.values())) + speed_min = min(speed_list) + speed_max = max(speed_list) + start_color = [255, 255, 255, 0.2] + end_color = [0, 0, 0, 0.2] + curr_color = [0, 0, 0, 0] + speed_limit = None for lane_idx in map.lane_dict: lane = map.lane_dict[lane_idx] + curr_color = [0, 0, 0, 0] + if fill_type == 'detailed': + speed_limit = speed_dict[lane_idx] + if speed_limit is not None: + lens = len(curr_color)-1 + for j in range(lens): + curr_color[j] = int(start_color[j]+(speed_limit-speed_min)/(speed_max - + speed_min)*(end_color[j]-start_color[j])) + curr_color[lens] = start_color[lens]+(speed_limit-speed_min)/(speed_max - + speed_min)*(end_color[lens]-start_color[lens]) for lane_seg in lane.segment_list: if lane_seg.type == 'Straight': start1 = lane_seg.start + lane_seg.width/2 * lane_seg.direction_lateral end1 = lane_seg.end + lane_seg.width/2 * lane_seg.direction_lateral - ax.plot([start1[0], end1[0]], [start1[1], end1[1]], color) start2 = lane_seg.start - lane_seg.width/2 * lane_seg.direction_lateral end2 = lane_seg.end - lane_seg.width/2 * lane_seg.direction_lateral - ax.plot([start2[0], end2[0]], [start2[1], end2[1]], color) + trace_x = [start1[0], end1[0], end2[0], start2[0], start1[0]] + trace_y = [start1[1], end1[1], end2[1], start2[1], start1[1]] + x_min = min(x_min, min(trace_x)) + y_min = min(y_min, min(trace_y)) + x_max = max(x_max, max(trace_x)) + y_max = max(y_max, max(trace_y)) + if fill_type == 'lines' or (fill_type == 'detailed' and speed_limit is None): + fig.add_trace(go.Scatter(x=trace_x, y=trace_y, + mode='lines', + line_color=color, + showlegend=False, + name='lines')) + elif fill_type == 'detailed' and speed_limit is not None: + fig.add_trace(go.Scatter(x=trace_x, y=trace_y, + mode='lines', + line_color=color, + fill='toself', + fillcolor='rgba' + + str(tuple(curr_color)), + showlegend=False, + name='limit')) + elif fill_type == 'fill': + fig.add_trace(go.Scatter(x=trace_x, y=trace_y, + mode='lines', + line_color=color, + fill='toself', + fillcolor='rgba(0,0,0,0.1)', + showlegend=False, + # text=theta, + name='lines')) elif lane_seg.type == "Circular": phase_array = np.linspace( start=lane_seg.start_phase, stop=lane_seg.end_phase, num=100) r1 = lane_seg.radius - lane_seg.width/2 - x = np.cos(phase_array)*r1 + lane_seg.center[0] - y = np.sin(phase_array)*r1 + lane_seg.center[1] - ax.plot(x, y, color) - + x1 = (np.cos(phase_array)*r1 + lane_seg.center[0]).tolist() + y1 = (np.sin(phase_array)*r1 + lane_seg.center[1]).tolist() r2 = lane_seg.radius + lane_seg.width/2 - x = np.cos(phase_array)*r2 + lane_seg.center[0] - y = np.sin(phase_array)*r2 + lane_seg.center[1] - ax.plot(x, y, color) + x2 = (np.cos(phase_array)*r2 + + lane_seg.center[0]).tolist().reverse() + y2 = (np.sin(phase_array)*r2 + + lane_seg.center[1]).tolist().reverse() + trace_x = x1+x2+[x1[0]] + trace_y = y1+y2+[y1[0]] + x_min = min(x_min, min(trace_x)) + y_min = min(y_min, min(trace_y)) + x_max = max(x_max, max(trace_x)) + y_max = max(y_max, max(trace_y)) + if fill_type == 'lines': + fig.add_trace(go.Scatter(x=trace_x, y=trace_y, + mode='lines', + line_color=color, + showlegend=False, + name='lines')) + elif fill_type == 'detailed' and speed_limit != None: + fig.add_trace(go.Scatter(x=trace_x, y=trace_y, + mode='lines', + line_color=color, + fill='toself', + fillcolor='rgba' + + str(tuple(curr_color)), + showlegend=False, + name='lines')) + elif fill_type == 'fill': + fig.add_trace(go.Scatter(x=trace_x, y=trace_y, + mode='lines', + line_color=color, + fill='toself', + showlegend=False, + name='lines')) else: raise ValueError(f'Unknown lane segment type {lane_seg.type}') + if fill_type == 'detailed': + fig.add_trace(go.Scatter(x=[0], y=[0], + mode='markers', + marker=dict( + symbol='square', + size=16, + cmax=speed_max, + cmin=speed_min, + color='rgba(0,0,0,0)', + colorbar=dict( + title="Speed Limit", + orientation='h' + ), + colorscale=[ + [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]] + ), + showlegend=False, + )) + fig.update_xaxes(range=[x_min, x_max]) + fig.update_yaxes(range=[y_min, y_max]) return fig -def plotly_simulation_tree(root: AnalysisTreeNode, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color='b', fig=None, x_lim=None, y_lim=None): - if fig is None: - fig = go.Figure() - i = 0 - fg_color = ['rgb(31,119,180)', 'rgb(255,127,14)', 'rgb(44,160,44)', 'rgb(214,39,40)', 'rgb(148,103,189)', - 'rgb(140,86,75)', 'rgb(227,119,194)', 'rgb(127,127,127)', 'rgb(188,189,34)', 'rgb(23,190,207)'] - bg_color = ['rgba(31,119,180,0.2)', 'rgba(255,127,14,0.2)', 'rgba(44,160,44,0.2)', 'rgba(214,39,40,0.2)', 'rgba(148,103,189,0.2)', - 'rgba(140,86,75,0.2)', 'rgba(227,119,194,0.2)', 'rgba(127,127,127,0.2)', 'rgba(188,189,34,0.2)', 'rgba(23,190,207,0.2)'] - queue = [root] - while queue != []: - node = queue.pop(0) - traces = node.trace - print(node.mode) - # [[time,x,y,theta,v]...] - trace = np.array(traces[agent_id]) - # print(trace) - for y_dim in y_dim_list: - trace_y = trace[:, y_dim].tolist() - trace_x = trace[:, x_dim].tolist() - theta = [i/pi*180 for i in trace[:, x_dim+2]] - trace_x_rev = trace_x[::-1] - # print(trace_x) - trace_upper = [i+1 for i in trace_y] - trace_lower = [i-1 for i in trace_y] - trace_lower = trace_lower[::-1] - # print(trace_upper) - # print(trace[:, y_dim]) - fig.add_trace(go.Scatter(x=trace_x+trace_x_rev, y=trace_upper+trace_lower, - fill='toself', - fillcolor=bg_color[i % 10], - line_color='rgba(255,255,255,0)', - showlegend=False)) - fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim], - mode='lines', - line_color=fg_color[i % 10], - text=theta, - name='lines')) - i += 1 - queue += node.child - fig.update_traces(mode='lines') - return fig - - -def plot_simulation_tree(root: AnalysisTreeNode, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color='b', fig=None, x_lim=None, y_lim=None): - if fig is None: - fig = plt.figure() - - ax = fig.gca() - if x_lim is None: - x_lim = ax.get_xlim() - if y_lim is None: - y_lim = ax.get_ylim() - - x_min, x_max = x_lim - y_min, y_max = y_lim - - queue = [root] - while queue != []: - node = queue.pop(0) - traces = node.trace - print(node.mode) - # [[time,x,y,theta,v]...] - trace = np.array(traces[agent_id]) - # print(trace) - for y_dim in y_dim_list: - ax.plot(trace[:, x_dim], trace[:, y_dim], color) - x_min = min(x_min, trace[:, x_dim].min()) - x_max = max(x_max, trace[:, x_dim].max()) - y_min = min(y_min, trace[:, y_dim].min()) - y_max = max(y_max, trace[:, y_dim].max()) - queue += node.child - ax.set_xlim([x_min-1, x_max+1]) - ax.set_ylim([y_min-1, y_max+1]) - return fig - - -def generate_simulation_anime(root, map, fig=None): - if fig is None: - fig = plt.figure() - # fig = plot_map(map, 'g', fig) - timed_point_dict = {} - stack = [root] - ax = fig.gca() - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = ax.get_ylim() - while stack != []: - node = stack.pop() - traces = node.trace - for agent_id in traces: - trace = traces[agent_id] - color = 'b' - if agent_id == 'car2': - color = 'r' - for i in range(len(trace)): - x_min = min(x_min, trace[i][1]) - x_max = max(x_max, trace[i][1]) - y_min = min(y_min, trace[i][2]) - y_max = max(y_max, trace[i][2]) - if round(trace[i][0], 5) not in timed_point_dict: - timed_point_dict[round(trace[i][0], 5)] = [ - (trace[i][1:], color)] - else: - timed_point_dict[round(trace[i][0], 5)].append( - (trace[i][1:], color)) - stack += node.child - - frames = [] - for time_point in timed_point_dict: - point_list = timed_point_dict[time_point] - plt.xlim((x_min-2, x_max+2)) - plt.ylim((y_min-2, y_max+2)) - # plot_map(map, color='g', fig=fig) - for data in point_list: - point = data - color = data[1] - ax = plt.gca() - ax.plot([point[0]], [point[1]], markerfacecolor=color, - markeredgecolor=color, marker='.', markersize=20) - x_tail = point[0] - y_tail = point[1] - dx = np.cos(point[2])*point[3] - dy = np.sin(point[2])*point[3] - ax.arrow(x_tail, y_tail, dx, dy, head_width=1, head_length=0.5) - plt.pause(0.05) - plt.clf() - return fig - # img_buf = io.BytesIO() - # plt.savefig(img_buf, format = 'png') - # im = Image.open(img_buf) - # frames.append(im) - # plt.clf() - # frame_one = frames[0] - # frame_one.save(fn, format = "GIF", append_images = frames, save_all = True, duration = 100, loop = 0) +def check_dim(num_dim: int, x_dim: int = 1, y_dim: int = 2, print_dim_list: List(int) = None): + if x_dim <= 0 or x_dim >= num_dim: + raise ValueError(f'wrong x dimension value {x_dim}') + if y_dim <= 0 or y_dim >= num_dim: + raise ValueError(f'wrong y dimension value {y_dim}') + if print_dim_list is None: + return True + for i in print_dim_list: + if y_dim <= 0 or y_dim >= num_dim: + raise ValueError(f'wrong printed dimension value {i}') + return True -def plotly_simulation_anime(root, map=None, fig=None): - # make figure +def create_anime_dict(duration=10): fig_dict = { "data": [], "layout": {}, "frames": [] } - # fig = plot_map(map, 'g', fig) - timed_point_dict = {} - stack = [root] - - # print("plot") - # print(root.mode) - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = float('inf'), -float('inf') - # segment_start = set() - # previous_mode = {} - # for agent_id in root.mode: - # previous_mode[agent_id] = [] - - while stack != []: - node = stack.pop() - traces = node.trace - for agent_id in traces: - trace = np.array(traces[agent_id]) - - for i in range(len(trace)): - x_min = min(x_min, trace[i][1]) - x_max = max(x_max, trace[i][1]) - y_min = min(y_min, trace[i][2]) - y_max = max(y_max, trace[i][2]) - # print(round(trace[i][0], 2)) - time_point = round(trace[i][0], 2) - if time_point not in timed_point_dict: - timed_point_dict[time_point] = [ - {agent_id: trace[i][1:].tolist()}] - else: - init = False - for record in timed_point_dict[time_point]: - if list(record.values())[0] == trace[i][1:].tolist(): - init = True - break - if init == False: - timed_point_dict[time_point].append( - {agent_id: trace[i][1:].tolist()}) - time = round(trace[i][0], 2) - stack += node.child - # fill in most of layout - # print(segment_start) - # print(timed_point_dict.keys()) - - duration = int(600/time) fig_dict["layout"]["xaxis"] = { - "range": [(x_min-10), (x_max+10)], "title": "x position"} fig_dict["layout"]["yaxis"] = { - "range": [(y_min-2), (y_max+2)], "title": "y position"} fig_dict["layout"]["hovermode"] = "closest" fig_dict["layout"]["updatemenus"] = [ @@ -984,225 +951,29 @@ def plotly_simulation_anime(root, map=None, fig=None): "y": 0, "steps": [] } - # make data - point_list = timed_point_dict[0] - - print(point_list) - x_list = [] - y_list = [] - text_list = [] - for data in point_list: - trace = list(data.values())[0] - # print(trace) - x_list.append(trace[0]) - y_list.append(trace[1]) - text_list.append( - ('{:.2f}'.format(trace[2]/pi*180), '{:.3f}'.format(trace[3]))) - data_dict = { - "x": x_list, - "y": y_list, - "mode": "markers + text", - "text": text_list, - "textfont": dict(size=14, color="black"), - "textposition": "bottom center", - # "marker": { - # "sizemode": "area", - # "sizeref": 200000, - # "size": 2 - # }, - "name": "Current Position" - } - fig_dict["data"].append(data_dict) - - # make frames - for time_point in timed_point_dict: - - # print(time_point) - frame = {"data": [], "layout": { - "annotations": []}, "name": '{:.2f}'.format(time_point)} - # print(timed_point_dict[time_point][0]) - point_list = timed_point_dict[time_point] - # point_list = list(OrderedDict.fromkeys(timed_point_dict[time_point])) - # todokeyi - trace_x = [] - trace_y = [] - trace_theta = [] - trace_v = [] - for data in point_list: - trace = list(data.values())[0] - # print(trace) - trace_x.append(trace[0]) - trace_y.append(trace[1]) - trace_theta.append(trace[2]) - trace_v.append(trace[3]) - data_dict = { - "x": trace_x, - "y": trace_y, - "mode": "markers + text", - - # "text": [(round(trace_theta[i]/pi*180, 2), round(trace_v[i], 3)) for i in range(len(trace_theta))], - "text": [('{:.2f}'.format(trace_theta[i]/pi*180), '{:.3f}'.format(trace_v[i])) for i in range(len(trace_theta))], - "textfont": dict(size=14, color="black"), - "textposition": "bottom center", - # "marker": { - # "sizemode": "area", - # "sizeref": 200000, - # "size": 2 - # }, - "name": "current position", - # "show_legend": False - } - frame["data"].append(data_dict) - for i in range(len(trace_x)): - ax = np.cos(trace_theta[i])*trace_v[i] - ay = np.sin(trace_theta[i])*trace_v[i] - # print(trace_x[i]+ax, trace_y[i]+ay) - annotations_dict = {"x": trace_x[i]+ax, "y": trace_y[i]+ay, - # "xshift": ax, "yshift": ay, - "ax": trace_x[i], "ay": trace_y[i], - "arrowwidth": 2, - # "arrowside": 'end', - "showarrow": True, - # "arrowsize": 1, - "xref": 'x', "yref": 'y', - "axref": 'x', "ayref": 'y', - # "text": "erver", - "arrowhead": 1, - "arrowcolor": "black"} - frame["layout"]["annotations"].append(annotations_dict) - fig_dict["frames"].append(frame) - slider_step = {"args": [ - [time_point], - {"frame": {"duration": duration, "redraw": False}, - "mode": "immediate", - "transition": {"duration": duration}} - ], - "label": time_point, - "method": "animate"} - sliders_dict["steps"].append(slider_step) - # print(len(frame["layout"]["annotations"])) - - fig_dict["layout"]["sliders"] = [sliders_dict] - - fig = go.Figure(fig_dict) - fig = plotly_map(map, 'g', fig) - i = 0 - queue = [root] - previous_mode = {} - agent_list = [] - for agent_id in root.mode: - previous_mode[agent_id] = [] - agent_list.append(agent_id) - text_pos = 'middle center' - while queue != []: - node = queue.pop(0) - traces = node.trace - # print(node.mode) - # [[time,x,y,theta,v]...] - i = 0 - for agent_id in traces: - trace = np.array(traces[agent_id]) - # print(trace) - trace_y = trace[:, 2].tolist() - trace_x = trace[:, 1].tolist() - # theta = [i/pi*180 for i in trace[:, 3]] - - i = agent_list.index(agent_id) - color = colors[i % 5] - fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2], - mode='lines', - line_color=color, - text=[(round(trace[i, 3]/pi*180, 2), round(trace[i, 4], 3)) - for i in range(len(trace_y))], - showlegend=False) - # name='lines') - ) - if previous_mode[agent_id] != node.mode[agent_id]: - theta = trace[0, 3] - veh_mode = node.mode[agent_id][0] - if veh_mode == 'Normal': - text_pos = 'middle center' - elif veh_mode == 'Brake': - if theta >= -pi/2 and theta <= pi/2: - text_pos = 'middle left' - else: - text_pos = 'middle right' - elif veh_mode == 'Accelerate': - if theta >= -pi/2 and theta <= pi/2: - text_pos = 'middle right' - else: - text_pos = 'middle left' - elif veh_mode == 'SwitchLeft': - if theta >= -pi/2 and theta <= pi/2: - text_pos = 'top center' - else: - text_pos = 'bottom center' - elif veh_mode == 'SwitchRight': - if theta >= -pi/2 and theta <= pi/2: - text_pos = 'bottom center' - else: - text_pos = 'top center' - fig.add_trace(go.Scatter(x=[trace[0, 1]], y=[trace[0, 2]], - mode='markers+text', - line_color='rgba(255,255,255,0.3)', - text=str(agent_id)+': ' + - str(node.mode[agent_id][0]), - textposition=text_pos, - textfont=dict( - # family="sans serif", - size=10, - color="grey"), - showlegend=False, - )) - # i += 1 - previous_mode[agent_id] = node.mode[agent_id] - queue += node.child - fig.update_traces(showlegend=False) - # fig.update_annotations(textfont=dict(size=14, color="black")) - # print(fig.frames[0].layout["annotations"]) - return fig - # fig.show() - - -# The 'color' property is a color and may be specified as: -# - A hex string (e.g. '#ff0000') -# - An rgb/rgba string (e.g. 'rgb(255,0,0)') -# - An hsl/hsla string (e.g. 'hsl(0,100%,50%)') -# - An hsv/hsva string (e.g. 'hsv(0,100%,100%)') -# - A named CSS color: -# aliceblue, antiquewhite, aqua, aquamarine, azure, -# beige, bisque, black, blanchedalmond, blue, -# blueviolet, brown, burlywood, cadetblue, -# chartreuse, chocolate, coral, cornflowerblue, -# cornsilk, crimson, cyan, darkblue, darkcyan, -# darkgoldenrod, darkgray, darkgrey, darkgreen, -# darkkhaki, darkmagenta, darkolivegreen, darkorange, -# darkorchid, darkred, darksalmon, darkseagreen, -# darkslateblue, darkslategray, darkslategrey, -# darkturquoise, darkviolet, deeppink, deepskyblue, -# dimgray, dimgrey, dodgerblue, firebrick, -# floralwhite, forestgreen, fuchsia, gainsboro, -# ghostwhite, gold, goldenrod, gray, grey, green, -# greenyellow, honeydew, hotpink, indianred, indigo, -# ivory, khaki, lavender, lavenderblush, lawngreen, -# lemonchiffon, lightblue, lightcoral, lightcyan, -# lightgoldenrodyellow, lightgray, lightgrey, -# lightgreen, lightpink, lightsalmon, lightseagreen, -# lightskyblue, lightslategray, lightslategrey, -# lightsteelblue, lightyellow, lime, limegreen, -# linen, magenta, maroon, mediumaquamarine, -# mediumblue, mediumorchid, mediumpurple, -# mediumseagreen, mediumslateblue, mediumspringgreen, -# mediumturquoise, mediumvioletred, midnightblue, -# mintcream, mistyrose, moccasin, navajowhite, navy, -# oldlace, olive, olivedrab, orange, orangered, -# orchid, palegoldenrod, palegreen, paleturquoise, -# palevioletred, papayawhip, peachpuff, peru, pink, -# plum, powderblue, purple, red, rosybrown, -# royalblue, rebeccapurple, saddlebrown, salmon, -# sandybrown, seagreen, seashell, sienna, silver, -# skyblue, slateblue, slategray, slategrey, snow, -# springgreen, steelblue, tan, teal, thistle, tomato, -# turquoise, violet, wheat, white, whitesmoke, -# yellow, yellowgreen - + return fig_dict, sliders_dict + + +def get_text_pos(veh_mode): + if veh_mode == 'Normal': + text_pos = 'middle center' + text = 'N' + elif veh_mode == 'Brake': + text_pos = 'middle left' + text = 'B' + elif veh_mode == 'Accelerate': + text_pos = 'middle right' + text = 'A' + elif veh_mode == 'SwitchLeft': + text_pos = 'top center' + text = 'SL' + elif veh_mode == 'SwitchRight': + text_pos = 'bottom center' + text = 'SR' + elif veh_mode == 'Stop': + text_pos = 'middle center' + text = 'S' + else: + print(veh_mode) + raise ValueError + return text_pos, text diff --git a/dryvr_plus_plus/plotter/plotter2D_new.py b/dryvr_plus_plus/plotter/plotter2D_new.py deleted file mode 100644 index 0f8cd26c781efb5ef3b81bf408f7428f802117fa..0000000000000000000000000000000000000000 --- a/dryvr_plus_plus/plotter/plotter2D_new.py +++ /dev/null @@ -1,979 +0,0 @@ -""" -This file consist main plotter code for DryVR reachtube output -""" - -from __future__ import annotations -import numpy as np -from math import pi -import plotly.graph_objects as go -from typing import List, Tuple -import copy -# from dryvr_plus_plus.scene_verifier.analysis.analysis_tree_node import AnalysisTreeNode - -colors = [['#CC0000', '#FF0000', '#FF3333', '#FF6666', '#FF9999'], - ['#CC6600', '#FF8000', '#FF9933', '#FFB266', '#FFCC99'], - ['#CCCC00', '#FFFF00', '#FFFF33', '#FFFF66', '#FFFF99'], - ['#66CC00', '#80FF00', '#99FF33', '#B2FF66', '#CCFF99'], - ['#00CC00', '#00FF00', '#33FF33', '#66FF66', '#99FF99'], - ['#00CC66', '#00FF80', '#33FF99', '#66FFB2', '#99FFCC'], - ['#00CCCC', '#00FFFF', '#33FFFF', '#66FFFF', '#99FFFF'], - ['#0066CC', '#0080FF', '#3399FF', '#66B2FF', '#99CCFF'], - ['#0000CC', '#0000FF', '#3333FF', '#6666FF', '#9999FF'], - ['#6600CC', '#7F00FF', '#9933FF', '#B266FF', '#CC99FF'], - ['#CC00CC', '#FF00FF', '#FF33FF', '#FF66FF', '#FF99FF'], - ['#CC0066', '#FF007F', '#FF3399', '#FF66B2', '#FF99CC'] - ] -scheme_dict = {'red': 0, 'orange': 1, 'yellow': 2, 'yellowgreen': 3, 'lime': 4, - 'springgreen': 5, 'cyan': 6, 'cyanblue': 7, 'blue': 8, 'purple': 9, 'magenta': 10, 'pink': 11} -color_cnt = 0 -text_size = 8 -scale_factor = 0.25 -mode_point_color = 'rgba(0,0,0,0.5)' -mode_text_color = 'black' -duration = 10 - - -"""These 5 Functions below are high-level functions and are recommended to use.""" -""" -API -These 5 functions share the same API. - -- root: the root node of the trace, should be the return value of Scenario.verify() or Scenario.simulate(). -- map: the map of the scenario, templates are in dryvr_plus_plus.example.example_map.simple_map2.py. -- fig: the object of the figure, its type should be plotly.graph_objects.Figure(). -- x_dim: the dimension of x coordinate in the trace list of every time step. The default value is 1. -- y_dim: the dimension of y coordinate in the trace list of every time step. The default value is 2. -- map_type the way to draw the map. It should be 'lines' or 'fill' or 'detailed'. The default value is 'lines'. --- For the 'lines' mode, map is only drawn by margins of lanes. --- For the 'fill' mode, the lanes will be filled with semitransparent colors. --- For the 'detailed' mode, the lanes will be filled some colors according to the speed limits of lanes(if the information is given). - Otherwise, it is the same as the 'lines' mode. -- scale_type the way to scale the coordinate axises. It should be 'trace' or 'map'. The default value is 'trace'. --- For the 'trace' mode, the traces will be in the center of the plot with an appropriate scale. --- For the 'map' mode, the map will be in the center of the plot with an appropriate scale. -- print_dim_list the list containing the dimensions of data which will be shown directly or indirectly when the mouse hovers on the point. - The default value is None. And then all dimensions will be shown. -""" - - -def reachtube_anime(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim: int = 2, map_type='lines', scale_type='trace', print_dim_list=None): - """It gives the animation of the verfication.""" - agent_list = list(root.agent.keys()) - timed_point_dict = {} - stack = [root] - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = float('inf'), -float('inf') - # input check - num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1] - check_dim(num_dim, x_dim, y_dim, print_dim_list) - if print_dim_list is None: - print_dim_list = range(0, num_dim) - scheme_list = list(scheme_dict.keys()) - - while stack != []: - node = stack.pop() - traces = node.trace - for agent_id in traces: - trace = np.array(traces[agent_id]) - if trace[0][0] > 0: - trace = trace[4:] - for i in range(0, len(trace)-1, 2): - x_min = min(x_min, trace[i][x_dim]) - x_max = max(x_max, trace[i][x_dim]) - y_min = min(y_min, trace[i][y_dim]) - y_max = max(y_max, trace[i][y_dim]) - time_point = round(trace[i][0], 2) - rect = [trace[i][0:].tolist(), trace[i+1][0:].tolist()] - if time_point not in timed_point_dict: - timed_point_dict[time_point] = {agent_id: [rect]} - else: - if agent_id in timed_point_dict[time_point].keys(): - timed_point_dict[time_point][agent_id].append(rect) - else: - timed_point_dict[time_point][agent_id] = [rect] - - stack += node.child - fig_dict, sliders_dict = create_anime_dict(duration) - for time_point in timed_point_dict: - frame = {"data": [], "layout": { - "annotations": [], "shapes": []}, "name": str(time_point)} - agent_dict = timed_point_dict[time_point] - for agent_id, rect_list in agent_dict.items(): - for rect in rect_list: - shape_dict = { - "type": 'rect', - "x0": rect[0][x_dim], - "y0": rect[0][y_dim], - "x1": rect[1][x_dim], - "y1": rect[1][y_dim], - "fillcolor": 'rgba(0,0,0,0.5)', - "line": dict(color='rgba(255,255,255,0)'), - "visible": True - - } - frame["layout"]["shapes"].append(shape_dict) - - fig_dict["frames"].append(frame) - slider_step = {"args": [ - ['{:.2f}'.format(time_point)], - {"frame": {"duration": duration, "redraw": False}, - "mode": "immediate", - "transition": {"duration": duration}} - ], - "label": '{:.2f}'.format(time_point), - "method": "animate"} - sliders_dict["steps"].append(slider_step) - - fig_dict["layout"]["sliders"] = [sliders_dict] - - fig = go.Figure(fig_dict) - fig = draw_map(map=map, fig=fig, fill_type=map_type) - i = 0 - for agent_id in agent_list: - fig = reachtube_tree_single( - root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list) - i = (i+1) % 12 - if scale_type == 'trace': - queue = [root] - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = float('inf'), -float('inf') - i = 0 - queue = [root] - previous_mode = {} - for agent_id in root.mode: - previous_mode[agent_id] = [] - text_pos = 'middle center' - while queue != []: - node = queue.pop(0) - traces = node.trace - for agent_id in traces: - trace = np.array(traces[agent_id]) - if scale_type == 'trace': - x_min = min(x_min, min(trace[:, x_dim])) - x_max = max(x_max, max(trace[:, x_dim])) - y_min = min(y_min, min(trace[:, y_dim])) - y_max = max(y_max, max(trace[:, y_dim])) - if previous_mode[agent_id] != node.mode[agent_id]: - text_pos, text = get_text_pos(node.mode[agent_id][0]) - x0 = trace[0, x_dim] - x1 = trace[1, x_dim] - y0 = trace[0, y_dim] - y1 = trace[1, y_dim] - mode_point_color = colors[agent_list.index(agent_id) % 12][0] - fig.add_trace(go.Scatter(x=[(x0+x1)/2], y=[(y0+y1)/2], - mode='markers+text', - line_color=mode_point_color, - text=str(agent_id)+': ' + text, - textposition=text_pos, - opacity=0.5, - textfont=dict( - size=text_size, - color=mode_text_color), - showlegend=False, - )) - previous_mode[agent_id] = node.mode[agent_id] - queue += node.child - if scale_type == 'trace': - fig.update_xaxes( - range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) - fig.update_yaxes( - range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) - return fig - - -def reachtube_tree(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None): - """It statically shows all the traces of the verfication.""" - fig = draw_map(map=map, fig=fig, fill_type=map_type) - agent_list = list(root.agent.keys()) - # input check - num_dim = np.array(root.trace[agent_list[0]]).shape[1] - check_dim(num_dim, x_dim, y_dim, print_dim_list) - if print_dim_list is None: - print_dim_list = range(0, num_dim) - - scheme_list = list(scheme_dict.keys()) - i = 0 - for agent_id in agent_list: - fig = reachtube_tree_single( - root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list) - i = (i+1) % 12 - if scale_type == 'trace': - queue = [root] - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = float('inf'), -float('inf') - i = 0 - queue = [root] - previous_mode = {} - for agent_id in root.mode: - previous_mode[agent_id] = [] - text_pos = 'middle center' - while queue != []: - node = queue.pop(0) - traces = node.trace - i = 0 - for agent_id in traces: - trace = np.array(traces[agent_id]) - if scale_type == 'trace': - x_min = min(x_min, min(trace[:, x_dim])) - x_max = max(x_max, max(trace[:, x_dim])) - y_min = min(y_min, min(trace[:, y_dim])) - y_max = max(y_max, max(trace[:, y_dim])) - i = agent_list.index(agent_id) - if previous_mode[agent_id] != node.mode[agent_id]: - text_pos, text = get_text_pos(node.mode[agent_id][0]) - mode_point_color = colors[agent_list.index(agent_id) % 12][0] - fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]], - mode='markers+text', - line_color=mode_point_color, - opacity=0.5, - text=str(agent_id)+': ' + text, - textposition=text_pos, - textfont=dict( - size=text_size, - color=mode_text_color), - showlegend=False, - )) - previous_mode[agent_id] = node.mode[agent_id] - queue += node.child - if scale_type == 'trace': - fig.update_xaxes( - range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) - fig.update_yaxes( - range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) - return fig - - -def simulation_tree(root, map=None, fig=None, x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None): - """It statically shows all the traces of the simulation.""" - fig = draw_map(map=map, fig=fig, fill_type=map_type) - agent_list = list(root.agent.keys()) - # input check - num_dim = np.array(root.trace[agent_list[0]]).shape[1] - check_dim(num_dim, x_dim, y_dim, print_dim_list) - if print_dim_list is None: - print_dim_list = range(0, num_dim) - - scheme_list = list(scheme_dict.keys()) - i = 0 - for agent_id in agent_list: - fig = simulation_tree_single( - root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list) - i = (i+1) % 12 - if scale_type == 'trace': - queue = [root] - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = float('inf'), -float('inf') - i = 0 - queue = [root] - previous_mode = {} - for agent_id in root.mode: - previous_mode[agent_id] = [] - text_pos = 'middle center' - while queue != []: - node = queue.pop(0) - traces = node.trace - i = 0 - for agent_id in traces: - trace = np.array(traces[agent_id]) - if scale_type == 'trace': - x_min = min(x_min, min(trace[:, x_dim])) - x_max = max(x_max, max(trace[:, x_dim])) - y_min = min(y_min, min(trace[:, y_dim])) - y_max = max(y_max, max(trace[:, y_dim])) - i = agent_list.index(agent_id) - mode_point_color = colors[agent_list.index(agent_id) % 12][0] - if previous_mode[agent_id] != node.mode[agent_id]: - text_pos, text = get_text_pos(node.mode[agent_id][0]) - fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]], - mode='markers+text', - line_color=mode_point_color, - opacity=0.5, - text=str(agent_id)+': ' + text, - textposition=text_pos, - textfont=dict( - size=text_size, - color=mode_text_color - ), - showlegend=False, - )) - previous_mode[agent_id] = node.mode[agent_id] - queue += node.child - if scale_type == 'trace': - fig.update_xaxes( - range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) - fig.update_yaxes( - range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) - fig.update_xaxes(title='x') - fig.update_yaxes(title='y') - fig.update_layout(legend_title_text='Agent list') - return fig - - -def simulation_anime(root, map=None, fig=None, x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None): - """It gives the animation of the simulation without trail but is faster.""" - timed_point_dict = {} - stack = [root] - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = float('inf'), -float('inf') - # input check - num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1] - check_dim(num_dim, x_dim, y_dim, print_dim_list) - if print_dim_list is None: - print_dim_list = range(0, num_dim) - agent_list = list(root.agent.keys()) - while stack != []: - node = stack.pop() - traces = node.trace - for agent_id in traces: - trace = np.array(traces[agent_id]) - for i in range(len(trace)): - x_min = min(x_min, trace[i][x_dim]) - x_max = max(x_max, trace[i][x_dim]) - y_min = min(y_min, trace[i][y_dim]) - y_max = max(y_max, trace[i][y_dim]) - time_point = round(trace[i][0], 2) - tmp_trace = trace[i][0:].tolist() - if time_point not in timed_point_dict: - timed_point_dict[time_point] = {agent_id: [tmp_trace]} - else: - if agent_id not in timed_point_dict[time_point].keys(): - timed_point_dict[time_point][agent_id] = [tmp_trace] - elif tmp_trace not in timed_point_dict[time_point][agent_id]: - timed_point_dict[time_point][agent_id].append( - tmp_trace) - time = round(trace[i][0], 2) - stack += node.child - fig_dict, sliders_dict = create_anime_dict(duration) - # make data - trace_dict = timed_point_dict[0] - for agent_id, trace_list in trace_dict.items(): - color = colors[agent_list.index(agent_id) % 12][1] - x_list = [] - y_list = [] - text_list = [] - branch_cnt = 0 - for trace in trace_list: - x_list.append(trace[x_dim]) - y_list.append(trace[y_dim]) - text_list.append(['{:.2f}'.format(trace[i]) - for i in print_dim_list]) - branch_cnt += 1 - data_dict = { - "x": x_list, - "y": y_list, - "text": text_list, - "mode": "markers + text", - "textfont": dict(size=text_size, color="black"), - "textposition": "bottom center", - "marker": { - "color": color, - }, - "name": agent_id, - "showlegend": True - } - fig_dict["data"].append(data_dict) - # make frames - for time_point in timed_point_dict: - frame = {"data": [], "layout": { - "annotations": []}, "name": '{:.2f}'.format(time_point)} - point_list = timed_point_dict[time_point] - for agent_id, trace_list in point_list.items(): - color = colors[agent_list.index(agent_id) % 12][1] - x_list = [] - y_list = [] - text_list = [] - branch_cnt = 0 - for trace in trace_list: - x_list.append(trace[x_dim]) - y_list.append(trace[y_dim]) - text_list.append(['{:.2f}'.format(trace[i]) - for i in print_dim_list]) - branch_cnt += 1 - data_dict = { - "x": x_list, - "y": y_list, - "text": text_list, - "mode": "markers + text", - "marker": { - "color": color, - }, - "textfont": dict(size=text_size, color="black"), - "textposition": "bottom center", - # "name": "Branch-"+str(branch_cnt), - "name": agent_id, - "showlegend": True - } - frame["data"].append(data_dict) - fig_dict["frames"].append(frame) - slider_step = {"args": [ - ['{:.2f}'.format(time_point)], - {"frame": {"duration": duration, "redraw": True}, - "mode": "immediate", - "transition": {"duration": duration}} - ], - "label": '{:.2f}'.format(time_point), - "method": "animate"} - sliders_dict["steps"].append(slider_step) - - fig_dict["layout"]["sliders"] = [sliders_dict] - - fig = go.Figure(fig_dict) - fig = draw_map(map, 'rgba(0,0,0,1)', fig, map_type) - i = 0 - queue = [root] - previous_mode = {} - agent_list = list(root.agent.keys()) - for agent_id in root.mode: - previous_mode[agent_id] = [] - text_pos = 'middle center' - while queue != []: - node = queue.pop(0) - traces = node.trace - for agent_id in traces: - trace = np.array(traces[agent_id]) - mode_point_color = colors[agent_list.index(agent_id) % 12][0] - if previous_mode[agent_id] != node.mode[agent_id]: - text_pos, text = get_text_pos(node.mode[agent_id][0]) - fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]], - mode='markers+text', - line_color=mode_point_color, - text=str(agent_id)+': ' + text, - textposition=text_pos, - opacity=0.5, - textfont=dict( - size=text_size, - color=mode_text_color), - showlegend=False, - )) - previous_mode[agent_id] = node.mode[agent_id] - queue += node.child - if scale_type == 'trace': - fig.update_xaxes( - range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) - fig.update_yaxes( - range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) - fig.update_layout(legend_title_text='Agent list') - return fig - - -def simulation_anime_trail(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None): - """It gives the animation of the simulation with trail.""" - timed_point_dict = {} - stack = [root] - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = float('inf'), -float('inf') - # input check - num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1] - check_dim(num_dim, x_dim, y_dim, print_dim_list) - if print_dim_list is None: - print_dim_list = range(0, num_dim) - - while stack != []: - node = stack.pop() - traces = node.trace - for agent_id in traces: - trace = np.array(traces[agent_id]) - for i in range(len(trace)): - x_min = min(x_min, trace[i][x_dim]) - x_max = max(x_max, trace[i][x_dim]) - y_min = min(y_min, trace[i][y_dim]) - y_max = max(y_max, trace[i][y_dim]) - time_point = round(trace[i][0], 3) - tmp_trace = trace[i][0:].tolist() - if time_point not in timed_point_dict: - timed_point_dict[time_point] = {agent_id: [tmp_trace]} - else: - if agent_id not in timed_point_dict[time_point].keys(): - timed_point_dict[time_point][agent_id] = [tmp_trace] - elif tmp_trace not in timed_point_dict[time_point][agent_id]: - timed_point_dict[time_point][agent_id].append( - tmp_trace) - time = round(trace[i][0], 2) - stack += node.child - fig_dict, sliders_dict = create_anime_dict(duration) - time_list = list(timed_point_dict.keys()) - agent_list = list(root.agent.keys()) - trail_limit = min(10, len(time_list)) - trail_len = trail_limit - opacity_step = 1/trail_len - size_step = 2/trail_len - min_size = 5 - step = 2 - # # make data - trace_dict = timed_point_dict[0] - - for time_point in list(timed_point_dict.keys())[0:int(trail_limit/step)]: - trace_dict = timed_point_dict[time_point] - for agent_id, point_list in trace_dict.items(): - x_list = [] - y_list = [] - text_list = [] - for point in point_list: - x_list.append(point[x_dim]) - y_list.append(point[y_dim]) - text_list.append(['{:.2f}'.format(point[i]) - for i in print_dim_list]) - data_dict = { - "x": x_list, - "y": y_list, - "mode": "markers", - "text": text_list, - "textfont": dict(size=text_size, color="black"), - "visible": False, - "textposition": "bottom center", - "name": agent_id - } - fig_dict["data"].append(data_dict) - - # make frames - for time_point_id in range(trail_limit, len(time_list)): - time_point = time_list[time_point_id] - frame = {"data": [], "layout": { - "annotations": []}, "name": '{:.2f}'.format(time_point)} - for agent_id in agent_list: - color = colors[agent_list.index(agent_id) % 12][1] - for id in range(0, trail_len, step): - tmp_point_list = timed_point_dict[time_list[time_point_id-id]][agent_id] - trace_x = [] - trace_y = [] - text_list = [] - for point in tmp_point_list: - trace_x.append(point[x_dim]) - trace_y.append(point[y_dim]) - text_list.append(['{:.2f}'.format(point[i]) - for i in print_dim_list]) - if id == 0: - data_dict = { - "x": trace_x, - "y": trace_y, - "mode": "markers+text", - "text": text_list, - "textfont": dict(size=text_size, color="black"), - "textposition": "bottom center", - "visible": True, # 'legendonly' - "marker": { - "color": color, - "opacity": opacity_step*(trail_len-id), - "size": min_size + size_step*(trail_len-id) - }, - "name": agent_id, - "showlegend": True - } - else: - data_dict = { - "x": trace_x, - "y": trace_y, - "mode": "markers", - "text": text_list, - "visible": True, # 'legendonly' - "marker": { - "color": color, - "opacity": opacity_step*(trail_len-id), - "size": min_size + size_step*(trail_len-id) - }, - "name": agent_id, - "showlegend": True - } - frame["data"].append(data_dict) - - fig_dict["frames"].append(frame) - slider_step = {"args": [ - ['{:.2f}'.format(time_point)], - {"frame": {"duration": duration, "redraw": False}, - "mode": "immediate", - "transition": {"duration": duration}} - ], - "label": '{:.2f}'.format(time_point), - "method": "animate"} - sliders_dict["steps"].append(slider_step) - - fig_dict["layout"]["sliders"] = [sliders_dict] - - fig = go.Figure(fig_dict) - fig = draw_map(map, 'rgba(0,0,0,1)', fig, map_type) - i = 0 - queue = [root] - previous_mode = {} - agent_list = list(root.agent.keys()) - for agent_id in root.mode: - previous_mode[agent_id] = [] - text_pos = 'middle center' - while queue != []: - node = queue.pop(0) - traces = node.trace - i = 0 - for agent_id in traces: - trace = np.array(traces[agent_id]) - trace_y = trace[:, y_dim].tolist() - trace_x = trace[:, x_dim].tolist() - i = agent_list.index(agent_id) - mode_point_color = colors[agent_list.index(agent_id) % 12][0] - if previous_mode[agent_id] != node.mode[agent_id]: - text_pos, text = get_text_pos(node.mode[agent_id][0]) - fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]], - mode='markers+text', - line_color=mode_point_color, - text=str(agent_id)+': ' + text, - opacity=0.5, - textposition=text_pos, - textfont=dict( - size=text_size, - color=mode_text_color - ), - showlegend=False, - )) - previous_mode[agent_id] = node.mode[agent_id] - queue += node.child - if scale_type == 'trace': - fig.update_xaxes( - range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)]) - fig.update_yaxes( - range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)]) - fig.update_layout(legend_title_text='Agent list') - return fig - - -"""Functions below are low-level functions and usually are not called outside this file.""" - - -def reachtube_tree_single(root, agent_id, fig=go.Figure(), x_dim: int = 1, y_dim: int = 2, color=None, print_dim_list=None): - """It statically shows the verfication traces of one given agent.""" - global color_cnt - if color == None: - color = list(scheme_dict.keys())[color_cnt] - color_cnt = (color_cnt+1) % 12 - queue = [root] - show_legend = False - fillcolor = colors[scheme_dict[color]][4] - while queue != []: - node = queue.pop(0) - traces = node.trace - trace = np.array(traces[agent_id]) - max_id = len(trace)-1 - trace_x_odd = np.array([trace[i][x_dim] for i in range(0, max_id, 2)]) - trace_x_even = np.array([trace[i][x_dim] - for i in range(1, max_id+1, 2)]) - trace_y_odd = np.array([trace[i][y_dim] for i in range(0, max_id, 2)]) - trace_y_even = np.array([trace[i][y_dim] - for i in range(1, max_id+1, 2)]) - fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', - fill='toself', - fillcolor=fillcolor, - opacity=0.5, - line_color='rgba(255,255,255,0)', - showlegend=show_legend - )) - fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', - fill='toself', - fillcolor=fillcolor, - opacity=0.5, - line_color='rgba(255,255,255,0)', - showlegend=show_legend)) - fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', - fill='toself', - fillcolor=fillcolor, - opacity=0.5, - line_color='rgba(255,255,255,0)', - showlegend=show_legend - )) - fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines', - fill='toself', - fillcolor=fillcolor, - opacity=0.5, - line_color='rgba(255,255,255,0)', - showlegend=show_legend)) - queue += node.child - - queue = [root] - while queue != []: - node = queue.pop(0) - traces = node.trace - trace = np.array(traces[agent_id]) - max_id = len(trace)-1 - fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim], - mode='markers', - text=[ - ['{:.2f}'.format(trace[i, j])for j in print_dim_list] for i in range(0, trace.shape[0])], - line_color=colors[scheme_dict[color]][0], - marker={ - "sizemode": "area", - "sizeref": 200000, - "size": 2 - }, - name='lines', - showlegend=False)) - queue += node.child - return fig - - -def simulation_tree_single(root, agent_id, fig: go.Figure() = go.Figure(), x_dim: int = 1, y_dim: int = 2, color=None, print_dim_list=None): - """It statically shows the simulation traces of one given agent.""" - global color_cnt - queue = [root] - color_id = 0 - if color == None: - color = list(scheme_dict.keys())[color_cnt] - color_cnt = (color_cnt+1) % 12 - start_list = [] - end_list = [] - count_dict = {} - while queue != []: - node = queue.pop(0) - traces = node.trace - if agent_id not in traces.keys(): - return fig - trace = np.array(traces[agent_id]) - start = list(trace[0]) - end = list(trace[-1]) - if (start in start_list) and (end in end_list): - continue - time = tuple([round(start[0], 2), round(end[0], 2)]) - if time in count_dict.keys(): - count_dict[time] += 1 - else: - count_dict[time] = 1 - start_list.append(start) - end_list.append(end) - fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim], - mode='lines', - line_color=colors[scheme_dict[color] - ][color_id], - text=[ - ['{:.2f}'.format(trace[i, j])for j in print_dim_list] for i in range(trace.shape[0])], - legendgroup=agent_id, - legendgrouptitle_text=agent_id, - name=str(round(start[0], 2))+'-'+str(round(end[0], 2)) + - '-'+str(count_dict[time]), - showlegend=True)) - color_id = (color_id+4) % 5 - queue += node.child - fig.update_layout(legend=dict( - groupclick="toggleitem", - itemclick="toggle", - itemdoubleclick="toggleothers" - )) - return fig - - -def draw_map(map, color='rgba(0,0,0,1)', fig: go.Figure() = go.Figure(), fill_type='lines'): - """It draws the the map""" - x_min, x_max = float('inf'), -float('inf') - y_min, y_max = float('inf'), -float('inf') - if map is None: - return fig - if fill_type == 'detailed': - speed_dict = map.get_all_speed_limit() - speed_list = list(filter(None, speed_dict.values())) - speed_min = min(speed_list) - speed_max = max(speed_list) - start_color = [255, 255, 255, 0.2] - end_color = [0, 0, 0, 0.2] - curr_color = [0, 0, 0, 0] - speed_limit = None - for lane_idx in map.lane_dict: - lane = map.lane_dict[lane_idx] - curr_color = [0, 0, 0, 0] - if fill_type == 'detailed': - speed_limit = speed_dict[lane_idx] - if speed_limit is not None: - lens = len(curr_color)-1 - for j in range(lens): - curr_color[j] = int(start_color[j]+(speed_limit-speed_min)/(speed_max - - speed_min)*(end_color[j]-start_color[j])) - curr_color[lens] = start_color[lens]+(speed_limit-speed_min)/(speed_max - - speed_min)*(end_color[lens]-start_color[lens]) - for lane_seg in lane.segment_list: - if lane_seg.type == 'Straight': - start1 = lane_seg.start + lane_seg.width/2 * lane_seg.direction_lateral - end1 = lane_seg.end + lane_seg.width/2 * lane_seg.direction_lateral - start2 = lane_seg.start - lane_seg.width/2 * lane_seg.direction_lateral - end2 = lane_seg.end - lane_seg.width/2 * lane_seg.direction_lateral - trace_x = [start1[0], end1[0], end2[0], start2[0], start1[0]] - trace_y = [start1[1], end1[1], end2[1], start2[1], start1[1]] - x_min = min(x_min, min(trace_x)) - y_min = min(y_min, min(trace_y)) - x_max = max(x_max, max(trace_x)) - y_max = max(y_max, max(trace_y)) - if fill_type == 'lines' or (fill_type == 'detailed' and speed_limit is None): - fig.add_trace(go.Scatter(x=trace_x, y=trace_y, - mode='lines', - line_color=color, - showlegend=False, - name='lines')) - elif fill_type == 'detailed' and speed_limit is not None: - fig.add_trace(go.Scatter(x=trace_x, y=trace_y, - mode='lines', - line_color=color, - fill='toself', - fillcolor='rgba' + - str(tuple(curr_color)), - showlegend=False, - name='limit')) - elif fill_type == 'fill': - fig.add_trace(go.Scatter(x=trace_x, y=trace_y, - mode='lines', - line_color=color, - fill='toself', - fillcolor='rgba(0,0,0,0.1)', - showlegend=False, - # text=theta, - name='lines')) - elif lane_seg.type == "Circular": - phase_array = np.linspace( - start=lane_seg.start_phase, stop=lane_seg.end_phase, num=100) - r1 = lane_seg.radius - lane_seg.width/2 - x1 = (np.cos(phase_array)*r1 + lane_seg.center[0]).tolist() - y1 = (np.sin(phase_array)*r1 + lane_seg.center[1]).tolist() - r2 = lane_seg.radius + lane_seg.width/2 - x2 = (np.cos(phase_array)*r2 + - lane_seg.center[0]).tolist().reverse() - y2 = (np.sin(phase_array)*r2 + - lane_seg.center[1]).tolist().reverse() - trace_x = x1+x2+[x1[0]] - trace_y = y1+y2+[y1[0]] - x_min = min(x_min, min(trace_x)) - y_min = min(y_min, min(trace_y)) - x_max = max(x_max, max(trace_x)) - y_max = max(y_max, max(trace_y)) - if fill_type == 'lines': - fig.add_trace(go.Scatter(x=trace_x, y=trace_y, - mode='lines', - line_color=color, - showlegend=False, - name='lines')) - elif fill_type == 'detailed' and speed_limit != None: - fig.add_trace(go.Scatter(x=trace_x, y=trace_y, - mode='lines', - line_color=color, - fill='toself', - fillcolor='rgba' + - str(tuple(curr_color)), - showlegend=False, - name='lines')) - elif fill_type == 'fill': - fig.add_trace(go.Scatter(x=trace_x, y=trace_y, - mode='lines', - line_color=color, - fill='toself', - showlegend=False, - name='lines')) - else: - raise ValueError(f'Unknown lane segment type {lane_seg.type}') - if fill_type == 'detailed': - fig.add_trace(go.Scatter(x=[0], y=[0], - mode='markers', - marker=dict( - symbol='square', - size=16, - cmax=speed_max, - cmin=speed_min, - color='rgba(0,0,0,0)', - colorbar=dict( - title="Speed Limit", - orientation='h' - ), - colorscale=[ - [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]] - ), - showlegend=False, - )) - fig.update_xaxes(range=[x_min, x_max]) - fig.update_yaxes(range=[y_min, y_max]) - return fig - - -def check_dim(num_dim: int, x_dim: int = 1, y_dim: int = 2, print_dim_list: List(int) = None): - if x_dim <= 0 or x_dim >= num_dim: - raise ValueError(f'wrong x dimension value {x_dim}') - if y_dim <= 0 or y_dim >= num_dim: - raise ValueError(f'wrong y dimension value {y_dim}') - if print_dim_list is None: - return True - for i in print_dim_list: - if y_dim <= 0 or y_dim >= num_dim: - raise ValueError(f'wrong printed dimension value {i}') - return True - - -def create_anime_dict(duration=10): - fig_dict = { - "data": [], - "layout": {}, - "frames": [] - } - fig_dict["layout"]["xaxis"] = { - "title": "x position"} - fig_dict["layout"]["yaxis"] = { - "title": "y position"} - fig_dict["layout"]["hovermode"] = "closest" - fig_dict["layout"]["updatemenus"] = [ - { - "buttons": [ - { - "args": [None, {"frame": {"duration": duration, "redraw": False}, - "fromcurrent": True, "transition": {"duration": duration, - "easing": "quadratic-in-out"}}], - "label": "Play", - "method": "animate" - }, - { - "args": [[None], {"frame": {"duration": 0, "redraw": False}, - "mode": "immediate", - "transition": {"duration": 0}}], - "label": "Pause", - "method": "animate" - } - ], - "direction": "left", - "pad": {"r": 10, "t": 87}, - "showactive": False, - "type": "buttons", - "x": 0.1, - "xanchor": "right", - "y": 0, - "yanchor": "top" - } - ] - sliders_dict = { - "active": 0, - "yanchor": "top", - "xanchor": "left", - "currentvalue": { - "font": {"size": 20}, - "prefix": "time:", - "visible": True, - "xanchor": "right" - }, - "transition": {"duration": duration, "easing": "cubic-in-out"}, - "pad": {"b": 10, "t": 50}, - "len": 0.9, - "x": 0.1, - "y": 0, - "steps": [] - } - return fig_dict, sliders_dict - - -def get_text_pos(veh_mode): - if veh_mode == 'Normal': - text_pos = 'middle center' - text = 'N' - elif veh_mode == 'Brake': - text_pos = 'middle left' - text = 'B' - elif veh_mode == 'Accelerate': - text_pos = 'middle right' - text = 'A' - elif veh_mode == 'SwitchLeft': - text_pos = 'top center' - text = 'SL' - elif veh_mode == 'SwitchRight': - text_pos = 'bottom center' - text = 'SR' - elif veh_mode == 'Stop': - text_pos = 'middle center' - text = 'S' - else: - print(veh_mode) - raise ValueError - return text_pos, text