@@ -20,25 +20,66 @@ numpy.random.seed(SEED)
20
20
## Components ##
21
21
22
22
# Dummy Sensors components
23
- component NoisyDistanceSystem (stddev, init_seed=1, overestimate=False ):
23
+ component RadarDistanceSystem (stddev):
24
24
""" A component that provides noisy distance to the car in front."""
25
25
sensors:
26
26
self.leadDist: float as sensors_distance
27
+ self.lead_car_width: float as lead_car_width
27
28
28
29
outputs:
29
30
dist: float
30
31
31
- state:
32
- seed: int = init_seed
32
+ body:
33
+ if lead_car_width < 1.8:
34
+ noise = random.gauss(sigma=stddev)
35
+ else:
36
+ noise = 0
37
+ noisy_distance = sensors_distance + noise
38
+ return {"dist": noisy_distance}
39
+
40
+ component LaserDistanceSystem(stddev):
41
+ """ A component that provides noisy distance to the car in front."""
42
+ sensors:
43
+ self.leadDist: float as sensors_distance
44
+ self.weather: float as weather
45
+
46
+ outputs:
47
+ dist: float
33
48
34
49
body:
35
- noise = random.gauss(sigma=stddev)
36
- if overestimate:
37
- noise = abs(noise)
50
+ if weather == 2 or weather == 3:
51
+ noise = random.gauss(sigma=stddev)
52
+ else:
53
+ noise = 0
38
54
noisy_distance = sensors_distance + noise
39
- state.seed = random.randint(1,1000000)
40
55
return {"dist": noisy_distance}
41
56
57
+ component MeanDistanceFilter():
58
+ inputs:
59
+ dist1: float
60
+ dist2: float
61
+
62
+ outputs:
63
+ mean_dist: float
64
+
65
+ body:
66
+ mean_dist = (dist1 + dist2)/2
67
+ return {"mean_dist": mean_dist}
68
+
69
+ component PerceptionSystem(stddev):
70
+ outputs:
71
+ dist: float
72
+
73
+ compose:
74
+ rds = RadarDistanceSystem(stddev)
75
+ lds = LaserDistanceSystem(stddev)
76
+ mdf = MeanDistanceFilter()
77
+
78
+ connect rds.dist to mdf.dist1
79
+ connect lds.dist to mdf.dist2
80
+
81
+ connect mdf.mean_dist to dist
82
+
42
83
component Speedometer():
43
84
""" Fetches and outputss ground truth speed."""
44
85
sensors:
@@ -226,7 +267,7 @@ component CarActionControls():
226
267
227
268
component Car(stddev, target_dist, max_speed, min_dist, max_accel, max_brake, abs_speed_err):
228
269
compose:
229
- ps = NoisyDistanceSystem (stddev)
270
+ ps = PerceptionSystem (stddev)
230
271
sm = Speedometer()
231
272
ds = DirectionSystem()
232
273
cs = ControlSystem(target_dist, max_speed, min_dist, max_accel, max_brake, abs_speed_err)
@@ -243,11 +284,44 @@ component Car(stddev, target_dist, max_speed, min_dist, max_accel, max_brake, ab
243
284
connect cs.steer to cac.steer
244
285
245
286
## Contracts ##
246
- contract AccurateDistance(perception_distance, abs_dist_err=0.5):
287
+ contract RadarManufacturerDistanceAccuracy(perception_distance, abs_dist_err=0.5):
288
+ """ Contract proving that perceived distance is relatively accurate."""
289
+ globals:
290
+ objects
291
+ workspace
292
+ params
293
+
294
+ outputs:
295
+ dist: float
296
+
297
+ definitions:
298
+ cars = [obj for obj in objects if hasattr(obj, "isVehicle") and obj.isVehicle and obj.position is not self.position]
299
+ lead_distances = {car: leadDistance(self, car, workspace.network, maxDistance=2*perception_distance) for car in cars}
300
+ lead_car = sorted(cars, key=lambda x: lead_distances[x])[0]
301
+ lead_dist = lead_distances[lead_car]
302
+ behind_car = lead_dist <= perception_distance
303
+
304
+ assumptions:
305
+ # Assume we are in a lane
306
+ always self._lane is not None
307
+
308
+ # Can reliably detect cars with width greater than or equal to 1.8 meters
309
+ params["lead_car_width"] >= 1.8
310
+
311
+ guarantees:
312
+ # Guarantee that if we're behind a car (in visible range), that the reported distance
313
+ # is relatively accurate.
314
+ always (behind_car implies (lead_dist-abs_dist_err <= dist <= lead_dist+abs_dist_err))
315
+ # Guarantee that if we are not behind a car (or out of visible range), that any reported
316
+ # distance is greater than our visible range.
317
+ always ((not behind_car) implies (dist > perception_distance+abs_dist_err))
318
+
319
+ contract LaserManufacturerDistanceAccuracy(perception_distance, abs_dist_err=0.5):
247
320
""" Contract proving that perceived distance is relatively accurate."""
248
321
globals:
249
322
objects
250
323
workspace
324
+ params
251
325
252
326
outputs:
253
327
dist: float
@@ -263,6 +337,9 @@ contract AccurateDistance(perception_distance, abs_dist_err=0.5):
263
337
# Assume we are in a lane
264
338
always self._lane is not None
265
339
340
+ # Can reliably detect cars in sunny or cloudy weather (no occluding atmospheric particles)
341
+ params["weather"] == 0 or params["weather"] == 1
342
+
266
343
guarantees:
267
344
# Guarantee that if we're behind a car (in visible range), that the reported distance
268
345
# is relatively accurate.
@@ -271,6 +348,99 @@ contract AccurateDistance(perception_distance, abs_dist_err=0.5):
271
348
# distance is greater than our visible range.
272
349
always ((not behind_car) implies (dist > perception_distance+abs_dist_err))
273
350
351
+ contract AccurateDistanceKnownConds(perception_distance, abs_dist_err=0.5):
352
+ """ Contract proving that perceived distance is relatively accurate outside of manufacturer spec conditions"""
353
+ globals:
354
+ objects
355
+ workspace
356
+ params
357
+
358
+ outputs:
359
+ dist: float
360
+
361
+ definitions:
362
+ cars = [obj for obj in objects if hasattr(obj, "isVehicle") and obj.isVehicle and obj.position is not self.position]
363
+ lead_distances = {car: leadDistance(self, car, workspace.network, maxDistance=2*perception_distance) for car in cars}
364
+ lead_car = sorted(cars, key=lambda x: lead_distances[x])[0]
365
+ lead_dist = lead_distances[lead_car]
366
+ behind_car = lead_dist <= perception_distance
367
+
368
+ assumptions:
369
+ # Assume we are in a lane
370
+ always self._lane is not None
371
+
372
+ (params["weather"] == 0 or params["weather"] == 1) and params["lead_car_width"] >= 1.8
373
+
374
+ guarantees:
375
+ # Guarantee that if we're behind a car (in visible range), that the reported distance
376
+ # is relatively accurate.
377
+ always (behind_car implies (lead_dist-abs_dist_err <= dist <= lead_dist+abs_dist_err))
378
+
379
+ contract AccurateDistanceUnknownConds(perception_distance, abs_dist_err=0.5):
380
+ """ Contract proving that perceived distance is relatively accurate outside of manufacturer spec conditions"""
381
+ globals:
382
+ objects
383
+ workspace
384
+ params
385
+
386
+ outputs:
387
+ dist: float
388
+
389
+ definitions:
390
+ cars = [obj for obj in objects if hasattr(obj, "isVehicle") and obj.isVehicle and obj.position is not self.position]
391
+ lead_distances = {car: leadDistance(self, car, workspace.network, maxDistance=2*perception_distance) for car in cars}
392
+ lead_car = sorted(cars, key=lambda x: lead_distances[x])[0]
393
+ lead_dist = lead_distances[lead_car]
394
+ behind_car = lead_dist <= perception_distance
395
+
396
+ assumptions:
397
+ # Assume we are in a lane
398
+ always self._lane is not None
399
+
400
+ not ((params["weather"] == 0 or params["weather"] == 1) and params["lead_car_width"] >= 1.8)
401
+
402
+ guarantees:
403
+ # Guarantee that if we're behind a car (in visible range), that the reported distance
404
+ # is relatively accurate.
405
+ always (behind_car implies (lead_dist-abs_dist_err <= dist <= lead_dist+abs_dist_err))
406
+
407
+ contract MeanDistanceFilterSemantics():
408
+ inputs:
409
+ dist1: float
410
+ dist2: float
411
+
412
+ outputs:
413
+ mean_dist: float
414
+
415
+ guarantees:
416
+ always (mean_dist == (dist1 + dist2)/2)
417
+
418
+ contract AccurateDistance(perception_distance, abs_dist_err=0.5):
419
+ """ Contract proving that perceived distance is relatively accurate."""
420
+ globals:
421
+ objects
422
+ workspace
423
+ params
424
+
425
+ outputs:
426
+ dist: float
427
+
428
+ definitions:
429
+ cars = [obj for obj in objects if hasattr(obj, "isVehicle") and obj.isVehicle and obj.position is not self.position]
430
+ lead_distances = {car: leadDistance(self, car, workspace.network, maxDistance=2*perception_distance) for car in cars}
431
+ lead_car = sorted(cars, key=lambda x: lead_distances[x])[0]
432
+ lead_dist = lead_distances[lead_car]
433
+ behind_car = lead_dist <= perception_distance
434
+
435
+ assumptions:
436
+ # Assume we are in a lane
437
+ always self._lane is not None
438
+
439
+ guarantees:
440
+ # Guarantee that if we're behind a car (in visible range), that the reported distance
441
+ # is relatively accurate.
442
+ always (behind_car implies (lead_dist-abs_dist_err <= dist <= lead_dist+abs_dist_err))
443
+
274
444
contract AccurateSpeed():
275
445
outputs:
276
446
speed: float
@@ -356,8 +526,6 @@ contract KeepsDistance(perception_distance, min_dist, max_speed, abs_dist_err, a
356
526
# Assume no one cuts in front us too closely
357
527
always ((next lead_dist) == (lead_dist - true_relative_speed))
358
528
359
- always (self.timestep == 0.1)
360
-
361
529
guarantees:
362
530
# Guarantee that we always stay at least min_dist behind the lead car
363
531
always lead_dist > min_dist
@@ -379,11 +547,41 @@ TARGET_DIST = 10
379
547
# Instantiate Car component and link to object.
380
548
implement "EgoCar" with Car(STDDEV, TARGET_DIST, MAX_SPEED, MIN_DIST, MAX_ACCEL, MAX_BRAKE, ABS_SPEED_ERR) as car
381
549
550
+ radar_accurate_distance = assume car.ps.rds satisfies RadarManufacturerDistanceAccuracy(
551
+ PERCEPTION_DISTANCE,
552
+ abs_dist_err=ABS_DIST_ERR)
553
+
554
+ laser_accurate_distance = assume car.ps.lds satisfies LaserManufacturerDistanceAccuracy(
555
+ PERCEPTION_DISTANCE,
556
+ abs_dist_err=ABS_DIST_ERR)
557
+
558
+ mean_dist_filter_sem = prove car.ps.mdf satisfies MeanDistanceFilterSemantics() \
559
+ using LeanContractProof(localPath("ScenicLean/"), "MeanDistanceFilterSemantics", localPath("repl"))
560
+
561
+ accurate_distance_known_raw = compose over car.ps:
562
+ use radar_accurate_distance
563
+ use laser_accurate_distance
564
+ use mean_dist_filter_sem
565
+
566
+ accurate_distance_known = refine accurate_distance_known_raw as AccurateDistanceKnownConds(
567
+ PERCEPTION_DISTANCE,
568
+ abs_dist_err=ABS_DIST_ERR) using LeanRefinementProof(localPath("ScenicLean/"), "AccurateDistanceKnownRefinement", localPath("repl"))
569
+
570
+ accurate_distance_unknown = test car.ps satisfies AccurateDistanceUnknownConds(
571
+ PERCEPTION_DISTANCE,
572
+ abs_dist_err=ABS_DIST_ERR),
573
+ using SimulationTesting(scenario=ENVIRONMENT, maxSteps=600, confidence=0.95, batchSize=10, verbose=False),
574
+ terminating after 30*60 seconds
575
+
576
+ accurate_distance = merge over car.ps:
577
+ use accurate_distance_known
578
+ use accurate_distance_unknown
579
+
382
580
accurate_distance = test car.ps satisfies AccurateDistance(
383
581
PERCEPTION_DISTANCE,
384
582
abs_dist_err=ABS_DIST_ERR),
385
- using SimulationTesting(scenario=ENVIRONMENT, maxSteps=6 , confidence=0.95, batchSize=10, verbose=False),
386
- terminating after 100 samples
583
+ using SimulationTesting(scenario=ENVIRONMENT, maxSteps=600 , confidence=0.95, batchSize=10, verbose=False),
584
+ terminating after 5*60 seconds
387
585
388
586
accurate_speed = assume car.sm satisfies AccurateSpeed()
389
587
0 commit comments