Skip to content

Commit 97329e4

Browse files
authored
longitudinal maneuvers: add report for longitudinal mpc tuning (#37030)
1 parent d76f756 commit 97329e4

File tree

1 file changed

+276
-0
lines changed

1 file changed

+276
-0
lines changed
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
import io
2+
import sys
3+
import markdown
4+
import numpy as np
5+
import matplotlib.pyplot as plt
6+
from openpilot.selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver
7+
from openpilot.selfdrive.controls.tests.test_following_distance import desired_follow_distance
8+
9+
TIME = 0
10+
EGO_V = 3
11+
EGO_A = 5
12+
LEAD_DISTANCE= 2
13+
14+
axis_labels = ['Time (s)',
15+
'Ego position (m)',
16+
'Lead distance (m)',
17+
'Ego Velocity (m/s)',
18+
'Lead Velocity (m/s)',
19+
'Ego acceleration (m/s^2)',
20+
]
21+
22+
23+
def get_html_from_results(results, labels, AXIS):
24+
fig, ax = plt.subplots(figsize=(16, 8))
25+
for idx, speed in enumerate(list(results.keys())):
26+
ax.plot(results[speed][:, TIME], results[speed][:, AXIS], label=labels[idx])
27+
28+
ax.set_xlabel('Time (s)')
29+
ax.set_ylabel(axis_labels[AXIS])
30+
ax.legend(bbox_to_anchor=(1.02, 1), loc='upper left', borderaxespad=0)
31+
ax.grid(True, linestyle='--', alpha=0.7)
32+
ax.text(-0.075, 0.5, '.', transform=ax.transAxes, color='none')
33+
34+
fig_buffer = io.StringIO()
35+
fig.savefig(fig_buffer, format='svg', bbox_inches='tight')
36+
plt.close(fig)
37+
return fig_buffer.getvalue() + '<br/>'
38+
39+
40+
htmls = []
41+
42+
results = {}
43+
name = 'Resuming behind lead'
44+
labels = []
45+
for lead_accel in np.linspace(1.0, 4.0, 4):
46+
man = Maneuver(
47+
'',
48+
duration=11,
49+
initial_speed=0.0,
50+
lead_relevancy=True,
51+
initial_distance_lead=desired_follow_distance(0.0, 0.0),
52+
speed_lead_values=[0.0, 10 * lead_accel],
53+
cruise_values=[100, 100],
54+
prob_lead_values=[1.0, 1.0],
55+
breakpoints=[1., 11],
56+
)
57+
valid, results[lead_accel] = man.evaluate()
58+
labels.append(f'{lead_accel} m/s^2 lead acceleration')
59+
60+
htmls.append(markdown.markdown('# ' + name))
61+
htmls.append(get_html_from_results(results, labels, EGO_V))
62+
htmls.append(get_html_from_results(results, labels, EGO_A))
63+
64+
65+
results = {}
66+
name = 'Approaching stopped car from 140m'
67+
labels = []
68+
for speed in np.arange(0,45,5):
69+
man = Maneuver(
70+
name,
71+
duration=30.,
72+
initial_speed=float(speed),
73+
lead_relevancy=True,
74+
initial_distance_lead=140.,
75+
speed_lead_values=[0.0, 0.],
76+
breakpoints=[0., 30.],
77+
)
78+
valid, results[speed] = man.evaluate()
79+
results[speed][:,2] = results[speed][:,2] - results[speed][:,1]
80+
labels.append(f'{speed} m/s approach speed')
81+
82+
htmls.append(markdown.markdown('# ' + name))
83+
htmls.append(get_html_from_results(results, labels, EGO_A))
84+
htmls.append(get_html_from_results(results, labels, LEAD_DISTANCE))
85+
86+
87+
results = {}
88+
name = 'Following 5s oscillating lead'
89+
labels = []
90+
speed = np.int64(10)
91+
for oscil in np.arange(0, 10, 1):
92+
man = Maneuver(
93+
'',
94+
duration=30.,
95+
initial_speed=float(speed),
96+
lead_relevancy=True,
97+
initial_distance_lead=desired_follow_distance(speed, speed),
98+
speed_lead_values=[speed, speed, speed - oscil, speed + oscil, speed - oscil, speed + oscil, speed - oscil],
99+
breakpoints=[0.,2., 5, 8, 15, 18, 25.],
100+
)
101+
valid, results[oscil] = man.evaluate()
102+
labels.append(f'{oscil} m/s oscilliation size')
103+
104+
htmls.append(markdown.markdown('# ' + name))
105+
htmls.append(get_html_from_results(results, labels, EGO_V))
106+
htmls.append(get_html_from_results(results, labels, EGO_A))
107+
108+
109+
110+
results = {}
111+
name = 'Speed profile when converging to steady state lead at 30m/s'
112+
labels = []
113+
for distance in np.arange(20, 140, 10):
114+
man = Maneuver(
115+
'',
116+
duration=50,
117+
initial_speed=30.0,
118+
lead_relevancy=True,
119+
initial_distance_lead=distance,
120+
speed_lead_values=[30.0],
121+
breakpoints=[0.],
122+
)
123+
valid, results[distance] = man.evaluate()
124+
results[distance][:,2] = results[distance][:,2] - results[distance][:,1]
125+
labels.append(f'{distance} m initial distance')
126+
127+
htmls.append(markdown.markdown('# ' + name))
128+
htmls.append(get_html_from_results(results, labels, EGO_V))
129+
htmls.append(get_html_from_results(results, labels, LEAD_DISTANCE))
130+
131+
132+
results = {}
133+
name = 'Speed profile when converging to steady state lead at 20m/s'
134+
labels = []
135+
for distance in np.arange(20, 140, 10):
136+
man = Maneuver(
137+
'',
138+
duration=50,
139+
initial_speed=20.0,
140+
lead_relevancy=True,
141+
initial_distance_lead=distance,
142+
speed_lead_values=[20.0],
143+
breakpoints=[0.],
144+
)
145+
valid, results[distance] = man.evaluate()
146+
results[distance][:,2] = results[distance][:,2] - results[distance][:,1]
147+
labels.append(f'{distance} m initial distance')
148+
149+
htmls.append(markdown.markdown('# ' + name))
150+
htmls.append(get_html_from_results(results, labels, EGO_V))
151+
htmls.append(get_html_from_results(results, labels, LEAD_DISTANCE))
152+
153+
154+
results = {}
155+
name = 'Following car at 30m/s that comes to a stop'
156+
labels = []
157+
for stop_time in np.arange(4, 14, 1):
158+
man = Maneuver(
159+
'',
160+
duration=50,
161+
initial_speed=30.0,
162+
lead_relevancy=True,
163+
initial_distance_lead=60.0,
164+
speed_lead_values=[30.0, 30.0, 0.0, 0.0],
165+
breakpoints=[0., 20., 20 + stop_time, 30 + stop_time],
166+
)
167+
valid, results[stop_time] = man.evaluate()
168+
results[stop_time][:,2] = results[stop_time][:,2] - results[stop_time][:,1]
169+
labels.append(f'{stop_time} seconds stop time')
170+
171+
htmls.append(markdown.markdown('# ' + name))
172+
htmls.append(get_html_from_results(results, labels, EGO_A))
173+
htmls.append(get_html_from_results(results, labels, LEAD_DISTANCE))
174+
175+
176+
results = {}
177+
name = 'Response to cut-in at half follow distance'
178+
labels = []
179+
for speed in np.arange(0, 40, 5):
180+
man = Maneuver(
181+
'',
182+
duration=10,
183+
initial_speed=float(speed),
184+
lead_relevancy=True,
185+
initial_distance_lead=desired_follow_distance(speed, speed)/2,
186+
speed_lead_values=[speed, speed, speed],
187+
cruise_values=[speed, speed, speed],
188+
prob_lead_values=[0.0, 0.0, 1.0],
189+
breakpoints=[0., 5.0, 5.01],
190+
)
191+
valid, results[speed] = man.evaluate()
192+
labels.append(f'{speed} m/s speed')
193+
194+
htmls.append(markdown.markdown('# ' + name))
195+
htmls.append(get_html_from_results(results, labels, EGO_A))
196+
htmls.append(get_html_from_results(results, labels, LEAD_DISTANCE))
197+
198+
199+
results = {}
200+
name = 'Follow a lead that accelerates at 2m/s^2 until steady state speed'
201+
labels = []
202+
for speed in np.arange(0, 40, 5):
203+
man = Maneuver(
204+
'',
205+
duration=50,
206+
initial_speed=0.0,
207+
lead_relevancy=True,
208+
initial_distance_lead=desired_follow_distance(0.0, 0.0),
209+
speed_lead_values=[0.0, 0.0, speed],
210+
prob_lead_values=[1.0, 1.0, 1.0],
211+
breakpoints=[0., 1.0, speed/2],
212+
)
213+
valid, results[speed] = man.evaluate()
214+
labels.append(f'{speed} m/s speed')
215+
216+
htmls.append(markdown.markdown('# ' + name))
217+
htmls.append(get_html_from_results(results, labels, EGO_V))
218+
htmls.append(get_html_from_results(results, labels, EGO_A))
219+
220+
221+
results = {}
222+
name = 'From stop to cruise'
223+
labels = []
224+
for speed in np.arange(0, 40, 5):
225+
man = Maneuver(
226+
'',
227+
duration=50,
228+
initial_speed=0.0,
229+
lead_relevancy=True,
230+
initial_distance_lead=desired_follow_distance(0.0, 0.0),
231+
speed_lead_values=[0.0, 0.0],
232+
cruise_values=[0.0, speed],
233+
prob_lead_values=[0.0, 0.0],
234+
breakpoints=[1., 1.01],
235+
)
236+
valid, results[speed] = man.evaluate()
237+
labels.append(f'{speed} m/s speed')
238+
239+
htmls.append(markdown.markdown('# ' + name))
240+
htmls.append(get_html_from_results(results, labels, EGO_V))
241+
htmls.append(get_html_from_results(results, labels, EGO_A))
242+
243+
244+
results = {}
245+
name = 'From cruise to min'
246+
labels = []
247+
for speed in np.arange(10, 40, 5):
248+
man = Maneuver(
249+
'',
250+
duration=50,
251+
initial_speed=float(speed),
252+
lead_relevancy=True,
253+
initial_distance_lead=desired_follow_distance(0.0, 0.0),
254+
speed_lead_values=[0.0, 0.0],
255+
cruise_values=[speed, 10.0],
256+
prob_lead_values=[0.0, 0.0],
257+
breakpoints=[1., 1.01],
258+
)
259+
valid, results[speed] = man.evaluate()
260+
labels.append(f'{speed} m/s speed')
261+
262+
htmls.append(markdown.markdown('# ' + name))
263+
htmls.append(get_html_from_results(results, labels, EGO_V))
264+
htmls.append(get_html_from_results(results, labels, EGO_A))
265+
266+
if len(sys.argv) < 2:
267+
file_name = 'long_mpc_tune_report.html'
268+
else:
269+
file_name = sys.argv[1]
270+
271+
with open(file_name, 'w') as f:
272+
f.write(markdown.markdown('# MPC longitudinal tuning report'))
273+
274+
with open(file_name, 'a') as f:
275+
for html in htmls:
276+
f.write(html)

0 commit comments

Comments
 (0)