diff --git a/tests/syntax/test_pruning.py b/tests/syntax/test_pruning.py index 6a0c693f6..859772c44 100644 --- a/tests/syntax/test_pruning.py +++ b/tests/syntax/test_pruning.py @@ -1,10 +1,8 @@ -import math -import random - import pytest from scenic.core.errors import InconsistentScenarioError -from scenic.core.vectors import Vector +from scenic.core.regions import PointInRegionDistribution +from scenic.core.vectors import Vector, VectorOperatorDistribution from tests.utils import compileScenic, sampleEgo, sampleParamP @@ -164,21 +162,38 @@ def test_visibility_pruning(): """Test visibility pruning in general. The following scenarios are equivalent except for how they specify that foo - must be visible from ego. The size of the workspace and the visibleDistance - of ego are chosen such that without pruning the chance of sampling a valid - scene over 100 tries is 1-(1-(3.14*2**2)/(1e10**2))**100 = ~1e-18. - Assuming the approximately buffered volume of the viewRegion has a 50% chance of - rejecting (i.e. it is twice as large as the true buffered viewRegion, which testing - indicates in this case has about a 10% increase in volume for this case), the chance - of not finding a sample in 100 iterations is 1e-31. - - We also want to confirm that we aren't pruning too much, i.e. placing the position - in the viewRegion instead of at any point where the object intersects the view region. - Because of this, we want to see at least one sample where the position is outside - the viewRegion but the object intersects the viewRegion. The chance of this happening - per sample is ((1 / 2)**2), so by repeating the process 30 times we have - ~1e-19 chance of not getting a single point in this zone. + must be visible from ego. Without visibility pruning, sampling a valid scene + would be extremely unlikely because the workspace is enormous compared to ego's + visible region. + + We check two things. First, sampled positions must remain within distance 2 of + ego, which is the maximum distance at which the spheroid can still intersect + ego's visible region. Second, to ensure pruning is not too aggressive, we check + the conditioned/pruned region directly and verify that it still extends beyond + distance 1 from ego, so the outer band where the object intersects the view + region is still available. """ + + def assert_pruned_region_reaches_outer_band(scenario): + foo = scenario.objects[1] + conditioned = foo.position._conditioned + + if isinstance(conditioned, PointInRegionDistribution): + base = conditioned.region + offset = Vector(0, 0, 0) + else: + assert isinstance(conditioned, VectorOperatorDistribution) + base = conditioned.object.region + offset = conditioned.operands[0] + + max_dist = max( + (Vector(x, y, base.z) + offset).distanceTo(Vector(0, 0, 0)) + for poly in base.polygons.geoms + for x, y in poly.exterior.coords + ) + assert max_dist <= 2 + 1e-6 + assert max_dist > 1 + 1e-6 + # requireVisible scenario = compileScenic( """ @@ -193,7 +208,7 @@ def test_visibility_pruning(): ) positions = [sampleParamP(scenario, maxIterations=100) for i in range(30)] assert all(pos.distanceTo(Vector(0, 0, 0)) <= 2 for pos in positions) - assert any(pos.distanceTo(Vector(0, 0, 0)) >= 1 for pos in positions) + assert_pruned_region_reaches_outer_band(scenario) # visible scenario = compileScenic( @@ -208,7 +223,7 @@ def test_visibility_pruning(): ) positions = [sampleParamP(scenario, maxIterations=100) for i in range(30)] assert all(pos.distanceTo(Vector(0, 0, 0)) <= 2 for pos in positions) - assert any(pos.distanceTo(Vector(0, 0, 0)) >= 1 for pos in positions) + assert_pruned_region_reaches_outer_band(scenario) # requireVisible with offset baseOffsetVal = 0.0001 @@ -226,7 +241,7 @@ def test_visibility_pruning(): ) positions = [sampleParamP(scenario, maxIterations=100) for i in range(30)] assert all(pos.distanceTo(Vector(0, 0, 0)) <= 2 for pos in positions) - assert any(pos.distanceTo(Vector(0, 0, 0)) >= 1 for pos in positions) + assert_pruned_region_reaches_outer_band(scenario) assert all(pos.z == -baseOffsetVal for pos in positions) # visible with offset @@ -243,7 +258,7 @@ def test_visibility_pruning(): ) positions = [sampleParamP(scenario, maxIterations=100) for i in range(30)] assert all(pos.distanceTo(Vector(0, 0, 0)) <= 2 for pos in positions) - assert any(pos.distanceTo(Vector(0, 0, 0)) >= 1 for pos in positions) + assert_pruned_region_reaches_outer_band(scenario) assert all(pos.z == -baseOffsetVal for pos in positions)