Example #1
0
class TestImageAnalyzer(unittest.TestCase):
    def setUp(self):
        self.num_timestamps = 7
        self.fov_deg = 92
        self.fov_rad = math.radians(self.fov_deg)
        self.object_universe = ObjectUniverse(
            num_timestamps=self.num_timestamps)

        self.camera = Camera()
        self.camera.set_fov_deg(self.fov_deg).set_actual_position((0, 0))
        for timestamp in range(self.num_timestamps):
            self.camera.set_state_of_pan_motor_angle_at_timestamp(0, timestamp)

        self.viewable_object = ViewableObject()

        self.object_universe.add_camera(self.camera).\
                             add_viewable_objects(self.viewable_object)

        self.angles = [
            -math.pi / 4,
            -math.pi / 8,
            math.pi / 8,
            math.pi / 4,
        ]

        self.image_width = self.camera.get_image_generator().get_image_width()
        self.d = self.image_width / 2 / math.tan(self.fov_rad / 2)

        self.x_s = [self.d * math.tan(a) for a in self.angles]

        self.positions = [(self.d, x) for x in self.x_s]

        self.sequence = [0, 1, 0, 2, 3, 2, 1]

        for timestamp, s in enumerate(self.sequence):
            self.viewable_object.set_position_at_timestamp(
                self.positions[s], timestamp)

        self.subtended_angles = [
            math.pi / 8,
            -math.pi / 8,
            3 * math.pi / 8,
            math.pi / 8,
            -math.pi / 8,
            -math.pi / 4,
        ]

        self.image_analyzer = ImageAnalyzer(self.camera)
        self.image_analyzer.set_images(self.camera.get_image_generator(
        ).get_x_for_all_inview_objects_for_all_camera_time())

    def test_angles(self):

        for i, _ in enumerate(self.subtended_angles):
            a_s = self.image_analyzer.get_subtended_angles_for_all_objects(
                i, i + 1)
            self.assertAlmostEqual(a_s[self.viewable_object],
                                   self.subtended_angles[i])
class TestImageGeneratorZeroAngle(unittest.TestCase):
    def setUp(self):
        self.num_timestamps = 2
        self.fov = math.pi / 2
        self.object_universe = ObjectUniverse(
            num_timestamps=self.num_timestamps)

        self.camera = Camera()

        self.camera.set_fov_rad(math.pi / 2).\
                    set_actual_position((100,400)).\
                    set_gps_position((100,410)).\
                    set_gps_max_error(12).\
                    set_num_timestamps(self.num_timestamps)

        for timestamp in range(self.num_timestamps):
            self.camera.set_state_of_pan_motor_angle_at_timestamp(0, timestamp)

        self.viewable_objects = [
            StationaryObject((300, 599)),
            StationaryObject((300, 201)),
        ]
        self.object_universe.add_viewable_objects(self.viewable_objects)
        self.object_universe.add_camera(self.camera)

    def test_fov(self):
        self.camera.image_generator.get_x_for_all_inview_objects_for_all_camera_time(
        )
        self.assertEqual(self.camera.get_image_generator().fov, math.pi / 2)

    def test_d(self):
        self.camera.image_generator.get_x_for_all_inview_objects_for_all_camera_time(
        )
        self.assertAlmostEqual(self.camera.get_image_generator().d, 320)

    def test_get_x_remain_in_image_width(self):
        r = self.camera.get_image_generator(
        ).get_x_for_all_inview_objects_for_all_camera_time()

        for obj in self.viewable_objects:
            x = r[0][obj]
            self.assertLess(
                abs(x),
                self.camera.get_image_generator().get_image_width() / 2)

    def test_image_width_default(self):
        self.assertEqual(self.camera.get_image_generator().get_image_width(),
                         640)
Example #3
0
class TestCamera(unittest.TestCase):

    def setUp(self):
        self.num_timestamps = 100
        self.object_universe = ObjectUniverse(num_timestamps=self.num_timestamps)
        self.camera = Camera(fov_deg=90, actual_position=(0,0))

        self.in_view_positions = [(1,0), (2,1), (2,-1)]
        self.out_view_positions = [(-1,0), (1,2), (1,-2)]
        self.in_view_objects  = list(map(
            lambda pos: StationaryObject(pos, name='in_view'),
            self.in_view_positions)
        )
        self.out_view_objects = list(map(
            lambda pos: StationaryObject(pos, name='out_view'),
            self.out_view_positions)
        )

        self.object_universe.clear_viewable_objects().add_viewable_objects(self.in_view_objects + self.out_view_objects)
        self.object_universe.add_camera(self.camera)

    def test_object_universe_has_correct_objects(self):
        self.assertEqual(self.object_universe.get_num_viewable_objects(), 6)
        named_out_view = list(filter(lambda obj: obj.get_name() == 'out_view',
                                     self.object_universe.get_viewable_objects()))
        named_in_view  = list(filter(lambda obj: obj.get_name() == 'in_view',
                                     self.object_universe.get_viewable_objects()))
        self.assertEqual(len(named_in_view), 3)
        self.assertEqual(len(named_out_view), 3)

    def test_camera_viewable_objects(self):
        self.assertEqual(len(self.camera.get_objects_in_view(0)), 3)
        for obj in self.camera.get_objects_in_view(0):
            self.assertEqual(obj.get_name(), 'in_view')

    def test_camera_not_viewable_objects(self):
        self.assertEqual(len(self.camera.get_objects_out_view(0)), 3)
        for obj in self.camera.get_objects_out_view(0):
            self.assertEqual(obj.get_name(), 'out_view')

    def test_camera_state_history_length_changes_when_object_universe_num_timestamps_changes(self):
        self.assertEqual(self.camera.get_state_history_len(), self.num_timestamps)
        self.object_universe.set_num_timestamps(50)
        self.assertEqual(self.camera.get_state_history_len(), 50)
Example #4
0
class Demo:
    def __init__(self):

        # Setup physical environment
        self.num_timestamps = 100

        self.camera = Camera()
        self.camera.set_actual_position((100,300)).\
                    set_gps_position((100,290)).\
                    set_gps_max_error(10).\
                    set_fov_deg(70)
        for timestamp in range(self.num_timestamps):
            self.camera.set_pan_angle_deg(0, timestamp)

        self.cv = ComputerVision()
        self.camera.set_computer_vision(self.cv)

        self.boundary = Boundary([(150, 100), (150, 550), (300, 550),
                                  (300, 100)])

        self.viewable_objects = []
        for _ in range(20):
            self.viewable_objects.append(
                RandomlyMovingObject(boundary=self.boundary))

        self.object_universe = ObjectUniverse(
            num_timestamps=self.num_timestamps)
        self.object_universe.add_camera(self.camera).\
                             add_viewable_objects(self.viewable_objects)

        self.cv.set_cv_ids_for_all_camera_time()

        # Rendering
        renderable_objects = [
            self.boundary,
            self.object_universe,
        ]

        RenderOrchestrator(self.num_timestamps,
                           seconds_per_timestamp=0.2,
                           renderable_objects=renderable_objects).run()
Example #5
0
class TestImageRenderer(unittest.TestCase):
    def setUp(self, num_randomly_moving_objects=0):

        self.num_randomly_moving_objects = num_randomly_moving_objects

        self.num_timestamps = 100
        self.object_universe = ObjectUniverse(
            num_timestamps=self.num_timestamps)

        self.camera = Camera()
        self.camera.set_fov_rad(math.pi / 2).\
                    set_actual_position((100,400)).\
                    set_gps_position((100,410)).\
                    set_gps_max_error(12).\
                    set_num_timestamps(self.num_timestamps)
        for timestamp in range(self.num_timestamps):
            self.camera.set_state_of_pan_motor_angle_at_timestamp(0, timestamp)

        self.viewable_objects = []
        for y in range(100, 800, 50):
            self.viewable_objects.append(StationaryObject((301, y)))

        self.boundary = Boundary([(200, 200), (400, 200), (400, 600),
                                  (200, 600)])
        for _ in range(self.num_randomly_moving_objects):
            self.viewable_objects.append(
                RandomlyMovingObject(boundary=self.boundary))

        self.viewable_objects.append(RandomlyMovingTag(boundary=self.boundary))

        self.object_universe.add_camera(self.camera).\
                             add_viewable_objects(self.viewable_objects)

        self.camera.get_computer_vision().set_cv_ids_for_all_camera_time()

        self.image_renderer = ImageRenderer(self.camera.get_image_generator())
        self.image_renderer.set_computer_vision(
            self.camera.get_computer_vision())

        return self

    def test_default_image_width_is_640(self):
        self.assertEqual(self.camera.get_image_generator().get_image_width(),
                         640)
        self.assertEqual(self.image_renderer.get_image_width(), 640)

    def test_all_in_view_objects_are_projected_within_image_width(self):
        x_for_all_inview_objects = self.camera.image_generator.get_x_for_all_inview_objects_for_all_camera_time(
        )

        for x_s in x_for_all_inview_objects:
            for obj in x_s.keys():
                self.assertLess(abs(x_s[obj]),
                                self.image_renderer.get_image_width() / 2)

    def visualize(self):
        renderable_objects = [
            self.boundary,
            self.object_universe,
        ]

        RenderOrchestrator(self.num_timestamps,
                           seconds_per_timestamp=0.2,
                           renderable_objects=renderable_objects).run()
class TestBaseAngleCalibrator(unittest.TestCase):

    def setUp(self, tag_gps_angle_threshold=6, compass_err_deg=3.7):
        self.tag_gps_angle_threshold = tag_gps_angle_threshold
        self.compass_err_deg = compass_err_deg

        self.num_timestamps = 50
        self.tag_gps_angle_threshold = math.radians(self.tag_gps_angle_threshold)

        self.object_universe = ObjectUniverse(num_timestamps=self.num_timestamps)

        self.camera = Camera()
        self.camera.set_actual_position((100, 400)).\
                    set_gps_position((100,380)).\
                    set_gps_max_error(25).\
                    set_fov_rad(math.pi/2).\
                    set_compass_error_rad(math.radians(self.compass_err_deg))

        self.boundary = Boundary([(220,300), (420,100), (420,700), (220, 500)])

        self.tag = RandomlyMovingTag(boundary=self.boundary)
        self.viewable_objects = [self.tag]

        self.object_universe.add_camera(self.camera).\
                             add_viewable_objects(self.viewable_objects)

        for timestamp in range(self.num_timestamps):
            self.camera.set_state_of_pan_motor_angle_at_timestamp(0, timestamp)

        self.camera.get_computer_vision().set_cv_ids_for_all_camera_time()

        self.base_position_calibrator = BasePositionCalibrator(self.camera,
                                                               self.tag,
                                                               tag_gps_angle_threshold=self.tag_gps_angle_threshold)


        self.base_angle_calibrator = BaseAngleCalibrator(self.base_position_calibrator)

        return self

    def test_base_angle_calibrator_result_is_almost_equal_to_compass_error(self):
        calibrated_error = self.base_angle_calibrator.get_base_angle_error()
        compass_error = self.camera.get_compass_error_rad()
        self.assertAlmostEqual(calibrated_error, compass_error)

    def test_get_frame_returns_a_complete_frame(self):
        frame = self.base_angle_calibrator._get_frame()
        self.assertEqual(type(frame), dict)
        self.assertGreater(len(frame), 0)

    def test_get_tag_angle_relative_to_center_in_image_returns_an_angle(self):
        angle = self.base_angle_calibrator._get_tag_angle_relative_to_center_in_image()
        self.assertEqual(type(angle), float)

    def visualize(self):

        renderable_objects = [
            self.boundary,
            self.object_universe,
            self.base_position_calibrator,
        ]

        RenderOrchestrator(self.num_timestamps,
                           seconds_per_timestamp=0.2,
                           renderable_objects=renderable_objects).run()
class TestObjectMotionAnalyzer(unittest.TestCase):
    def setUp(self, num_randomly_moving_objects=10):
        self.num_randomly_moving_objects = num_randomly_moving_objects

        self.num_timestamps = 60
        self.tag_gps_angle_threshold = math.radians(7)

        self.object_universe = ObjectUniverse(
            num_timestamps=self.num_timestamps)

        self.camera = Camera()
        self.camera.set_actual_position((100, 400)).\
                    set_gps_position((100,380)).\
                    set_gps_max_error(25).\
                    set_fov_rad(math.pi/2)

        self.boundary = Boundary([(220, 300), (420, 100), (420, 700),
                                  (220, 500)])

        self.tag = RandomlyMovingTag(boundary=self.boundary)
        self.viewable_objects = [self.tag]

        for _ in range(self.num_randomly_moving_objects):
            self.viewable_objects.append(
                RandomlyMovingObject(boundary=self.boundary))

        self.object_universe.add_camera(self.camera).\
                             add_viewable_objects(self.viewable_objects)

        for timestamp in range(self.num_timestamps):
            self.camera.set_state_of_pan_motor_angle_at_timestamp(0, timestamp)

        self.camera.get_computer_vision().set_cv_ids_for_all_camera_time()

        self.object_motion_analyzer = ObjectMotionAnalyzer(
            self.camera,
            self.tag,
            tag_gps_angle_threshold=self.tag_gps_angle_threshold)

        self.frames = self.object_motion_analyzer.get_complete_frames()

        return self

    def test_get_c1_high_def_returns_a_linear_ring(self):
        ccs = self.object_motion_analyzer.get_circumcircles_for_object_for_all_frames(
            self.tag)
        for cc in ccs:
            self.assertEqual(type(cc.get_c1_high_def()), LinearRing)

    def test_get_c1_low_def_returns_a_linear_ring(self):
        ccs = self.object_motion_analyzer.get_circumcircles_for_object_for_all_frames(
            self.tag)
        for cc in ccs:
            self.assertEqual(type(cc.get_c1_low_def()), LinearRing)

    def test_get_c2_high_def_returns_a_linear_ring(self):
        ccs = self.object_motion_analyzer.get_circumcircles_for_object_for_all_frames(
            self.tag)
        for cc in ccs:
            self.assertEqual(type(cc.get_c2_high_def()), LinearRing)

    def test_get_c2_low_def_returns_a_linear_ring(self):
        ccs = self.object_motion_analyzer.get_circumcircles_for_object_for_all_frames(
            self.tag)
        for cc in ccs:
            self.assertEqual(type(cc.get_c2_low_def()), LinearRing)

    def test_intersection_with_error_circle_for_tag_always_returns_linestring(
            self):
        ccs = self.object_motion_analyzer.get_circumcircles_for_object_for_all_frames(
            self.tag)
        for cc in ccs:
            isect = cc.get_error_circle_intersection()
            self.assertEqual(type(isect), LineString)

    def test_get_all_cirumcircles_for_object_for_all_frames_returns_list_of_cc_objects(
            self):
        # The setup ensures that the randomly moving tag is in every frame.
        ccs = self.object_motion_analyzer.get_circumcircles_for_object_for_all_frames(
            self.tag)
        self.assertGreater(len(ccs), 0)
        for cc in ccs:
            self.assertEqual(type(cc), Circumcircles)

    def test_circumcircles_added_for_each_viewable_object_in_each_frame(self):
        for frame in self.frames:
            if not self.object_motion_analyzer.is_terminal_frame(frame):
                objs = self.object_motion_analyzer.get_in_view_objects(frame)
                self.assertEqual(len(objs),
                                 self.num_randomly_moving_objects + 1)
                for obj in self.object_motion_analyzer.get_in_view_objects(
                        frame):
                    self.assertIsInstance(
                        self.object_motion_analyzer.
                        get_circumcircles_for_object_in_frame(frame, obj),
                        Circumcircles)

    def test_angle_between_positions_is_greater_than_threshold(self):
        for frame in self.frames:
            if not self.object_motion_analyzer.is_terminal_frame(frame):
                self.assertGreater(
                    abs(self.object_motion_analyzer.get_tag_position_analyzer(
                    ).get_angle_between_positions(frame)),
                    self.tag_gps_angle_threshold)

    def test_rotation_same_as_tag_for_tag(self):
        for frame in self.frames:
            rot = self.object_motion_analyzer.get_rotation_same_as_tag(
                frame, self.tag)

            if self.object_motion_analyzer.is_terminal_frame(frame):
                self.assertEqual(rot, None)
            else:
                self.assertTrue(rot)

    def test_tag_circumcircles_always_intersect_error_circle(self):
        for frame in self.frames:
            if not self.object_motion_analyzer.is_terminal_frame(frame):
                tag = self.object_motion_analyzer.get_tag(frame)
                isects = self.object_motion_analyzer.get_circumcircles(
                    frame)[tag].get_intersects_error_circle()
                self.assertTrue(isects)

    def visualize(self):
        self.boundary_renderer = BoundaryRenderer(self.boundary)
        self.camera_renderer = CameraRenderer(self.camera)
        self.viewable_objects_renderer = ViewableObjectsRenderer(
            self.viewable_objects,
            computer_vision=self.camera.get_computer_vision())
        self.image_renderer = ImageRenderer(self.camera.get_image_generator())
        self.image_renderer.set_computer_vision(
            self.camera.get_computer_vision())
        self.circumcircle_renderer = BasePositionCalibratorRenderer(
            self.object_motion_analyzer)

        self.renderers = [
            self.camera_renderer,
            self.viewable_objects_renderer,
            self.boundary_renderer,
            self.image_renderer,
            self.circumcircle_renderer,
        ]

        self.animator = Animator(element_renderers=self.renderers,
                                 num_timestamps=self.num_timestamps,
                                 seconds_per_timestamp=0.2)

        TKRenderer().set_canvas_height(900).\
                     set_canvas_width(1000).\
                     set_scale(1).\
                     set_mouse_click_callback(self.animator.play).\
                     start_tk_event_loop()
Example #8
0
class TestObjectStatsProcessor(unittest.TestCase):
    def setUp(self):
        self.num_timestamps = 50
        self.tag_gps_angle_threshold = math.radians(6)

        self.object_universe = ObjectUniverse(
            num_timestamps=self.num_timestamps)

        self.camera = Camera()
        self.camera.set_actual_position((100, 400)).\
                    set_gps_position((100,380)).\
                    set_gps_max_error(25).\
                    set_fov_rad(math.pi/2)

        self.boundary = Boundary([(220, 300), (420, 100), (420, 700),
                                  (220, 500)])

        self.tag = RandomlyMovingTag(boundary=self.boundary)
        self.r_objs = []
        for _ in range(20):
            self.r_objs.append(RandomlyMovingObject(boundary=self.boundary))

        self.viewable_objects = [self.tag] + self.r_objs

        self.object_universe.add_camera(self.camera).\
                             add_viewable_objects(self.viewable_objects)

        for timestamp in range(self.num_timestamps):
            self.camera.set_state_of_pan_motor_angle_at_timestamp(0, timestamp)

        self.camera.get_computer_vision().set_cv_ids_for_all_camera_time()

        self.object_motion_analyzer = ObjectMotionAnalyzer(
            self.camera,
            self.tag,
            tag_gps_angle_threshold=self.tag_gps_angle_threshold)

        self.object_stats_processor = ObjectsStatsProcessor(
            self.object_motion_analyzer)

        return self

    def test_get_all_eliminated_before_timestamp(self):
        for timestamp in range(self.num_timestamps):
            eliminated = []
            for obj in self.object_stats_processor.get_processed_objects():
                if self.object_stats_processor.get_elimination_t(
                        obj
                ) != None and self.object_stats_processor.get_elimination_t(
                        obj) <= timestamp:
                    eliminated.append(obj)

            eliminated.sort(key=self.get_id)
            es = self.object_stats_processor.get_all_eliminated_before_timestamp(
                timestamp)
            es.sort(key=self.get_id)
            self.assertEqual(eliminated, es)

    def get_id(self, obj):
        return id(obj)

    def test_tag_is_top_ranked_object(self):
        self.assertEqual(self.object_stats_processor.get_top_ranked_object(),
                         self.tag)

    def test_all_ranked_objects_always_moved_same_direction_as_tag(self):
        ranked = self.object_stats_processor.get_ranked_objects()
        for obj in ranked:
            self.assertTrue(
                self.object_stats_processor.get_didnt_move_opposite_to_tag(
                    obj))

    def test_all_objects_eliminated_for_opposite_are_marked_eliminated_with_same_time_as_opposite_time(
            self):
        for obj in self.object_stats_processor.get_all_moved_oposite():
            self.assertTrue(
                self.object_stats_processor.get_did_move_opposite_to_tag(obj))
            self.assertEqual(
                self.object_stats_processor.get_moved_opposite_to_tag_t(obj),
                self.object_stats_processor.get_elimination_t(obj))

    def test_didnt_intersect_t_is_an_int_or_none(self):
        for obj in self.object_stats_processor.get_processed_objects():
            if self.object_stats_processor.get_didnt_intersect_error_circle_t(
                    obj) != None:
                self.assertEqual(
                    type(
                        self.object_stats_processor.
                        get_didnt_intersect_error_circle_t(obj)), int)

    def test_all_objects_never_moved_in_opposite_direction_are_marked_eliminated_if_they_have_fewer_intersections_than_top_ranked_objects(
            self):
        for obj in self.object_stats_processor.get_all_that_always_moved_same_direction_as_tag(
        ):
            if obj not in self.object_stats_processor.get_top_ranked_objects():
                self.assertTrue(
                    self.object_stats_processor.get_eliminated(obj))
                last_frame = self.object_stats_processor.get_object_motion_analyzer(
                ).get_tag_position_analyzer().get_last_complete_frame()
                early_time_of_last_frame = self.object_stats_processor.get_object_motion_analyzer(
                ).get_tag_position_analyzer().get_early_min_max_timestamp(
                    last_frame)
                self.assertEqual(
                    early_time_of_last_frame,
                    self.object_stats_processor.get_elimination_t(obj))

    def test_tag_always_intersects(self):
        o = self.object_stats_processor.get_processed_objects()
        t = self.object_stats_processor.get_didnt_intersect_error_circle_n(
            self.tag)
        self.assertEqual(
            self.object_stats_processor.get_didnt_intersect_error_circle_n(
                self.tag), 0)

    def test_get_to_ranked_objects_returns_all_with_same_didnt_intersect_n_as_top_ranked_object(
            self):
        top_ranked = self.object_stats_processor.get_top_ranked_object()
        top_ranked_n = self.object_stats_processor.get_didnt_intersect_error_circle_n(
            top_ranked)

        ranked_objs = self.object_stats_processor.get_ranked_objects()
        num_ranked_objs = len(ranked_objs)

        moved_opposite = self.object_stats_processor.get_all_moved_oposite()[0]

        for obj in ranked_objs:
            self.object_stats_processor._processed_objects[obj][
                self.object_stats_processor.
                didnt_intersect_error_circle_n] = top_ranked_n

        self.assertEqual(
            num_ranked_objs,
            len(self.object_stats_processor.get_top_ranked_objects()))

        self.object_stats_processor._processed_objects[moved_opposite][
            self.object_stats_processor.
            didnt_intersect_error_circle_n] = top_ranked_n
        self.object_stats_processor._processed_objects[moved_opposite][
            self.object_stats_processor.eliminated] = False
        self.object_stats_processor._processed_objects[moved_opposite][
            self.object_stats_processor.moved_opposite_to_tag_n] = 0
        self.object_stats_processor._processed_objects[moved_opposite][
            self.object_stats_processor.moved_opposite_to_tag_t] = None

        self.assertEqual(
            num_ranked_objs + 1,
            len(self.object_stats_processor.get_top_ranked_objects()))

    def visualize(self):
        self.boundary_renderer = BoundaryRenderer(self.boundary)
        self.camera_renderer = CameraRenderer(self.camera)
        self.viewable_objects_renderer = ViewableObjectsRenderer(
            self.viewable_objects,
            computer_vision=self.camera.get_computer_vision())
        self.image_renderer = ImageRenderer(self.camera.get_image_generator())
        self.image_renderer.set_computer_vision(
            self.camera.get_computer_vision())
        self.circumcircle_renderer = BasePositionCalibratorRenderer(
            self.object_motion_analyzer)

        self.renderers = [
            self.camera_renderer,
            self.viewable_objects_renderer,
            self.boundary_renderer,
            self.image_renderer,
            self.circumcircle_renderer,
        ]

        self.animator = Animator(element_renderers=self.renderers,
                                 num_timestamps=self.num_timestamps,
                                 seconds_per_timestamp=0.2)

        TKRenderer().set_canvas_height(900).\
                     set_canvas_width(1000).\
                     set_scale(1).\
                     set_mouse_click_callback(self.animator.play).\
                     start_tk_event_loop()
class TestImageGenerator(unittest.TestCase):
    def setUp(self):
        self.num_timestamps = 10
        self.fov = math.pi / 2
        self.image_width = 1000
        self.object_universe = ObjectUniverse(
            num_timestamps=self.num_timestamps)
        self.camera = Camera()

        self.camera.set_actual_position((1,1)).\
                    set_fov_rad(self.fov).\
                    set_num_timestamps(self.num_timestamps).\
                    set_range(50000)

        for timestamp in range(self.camera.get_num_timestamps()):
            self.camera.set_state_of_pan_motor_angle_at_timestamp_rad(
                math.pi / 4, timestamp)

        self.cv = ComputerVision()
        self.image_generator = ImageGenerator(image_width=self.image_width)
        self.camera.set_computer_vision(self.cv).\
                    set_image_generator(self.image_generator)

        self.viewable_objects = [
            StationaryObject((2, 1 + math.tan(math.pi / 8))),
            StationaryObject((1 + math.tan(math.pi / 8), 2)),
            StationaryObject((10000, 1.1)),
            StationaryObject((1.1, 10000)),
        ]
        self.object_universe.add_viewable_objects(self.viewable_objects)
        self.object_universe.add_camera(self.camera)

        self.d = self.image_width / (2 * math.tan(self.fov / 2))
        self.theta = math.pi / 8

    def test_d_calculation_for_image_generator(self):
        self.camera.get_image_generator(
        ).get_x_for_all_inview_objects_for_all_camera_time()
        self.assertEqual(self.d, self.image_generator.d)

    def test_theta_calculation_for_image_generator(self):
        self.camera.get_image_generator(
        ).get_x_for_all_inview_objects_for_all_camera_time()
        self.assertAlmostEqual(
            -self.theta,
            self.image_generator._get_theta_rad(self.viewable_objects[0], 0))
        self.assertAlmostEqual(
            self.theta,
            self.image_generator._get_theta_rad(self.viewable_objects[1], 0))

    def test_get_x_for_all_inview_objects_for_all_camera_time(self):

        r = self.image_generator.get_x_for_all_inview_objects_for_all_camera_time(
        )

        for timestamp in range(self.camera.get_num_timestamps()):
            self.assertAlmostEqual(r[timestamp][self.viewable_objects[0]],
                                   -self.d * math.tan(math.pi / 8))
            self.assertAlmostEqual(r[timestamp][self.viewable_objects[1]],
                                   self.d * math.tan(math.pi / 8))

    def test_get_x_for_distant_objects_at_edge_of_view_remain_in_image_width(
            self):

        r = self.image_generator.get_x_for_all_inview_objects_for_all_camera_time(
        )

        for obj in self.viewable_objects:
            x = r[0][obj]
            self.assertLess(abs(x), self.image_width / 2)
Example #10
0
class TestBasePositionCalibrator(unittest.TestCase):
    def setUp(self, num_randomly_moving_objects=10, tag_gps_angle_threshold=6):
        self.num_randomly_moving_objects = num_randomly_moving_objects

        self.num_timestamps = 50
        self.tag_gps_angle_threshold = math.radians(tag_gps_angle_threshold)

        self.object_universe = ObjectUniverse(
            num_timestamps=self.num_timestamps)

        self.camera = Camera()
        self.camera.set_actual_position((100, 400)).\
                    set_gps_position((100,380)).\
                    set_gps_max_error(25).\
                    set_fov_rad(math.pi/2)

        self.boundary = Boundary([(220, 300), (420, 100), (420, 700),
                                  (220, 500)])

        self.tag = RandomlyMovingTag(boundary=self.boundary)
        self.r_objs = []
        for _ in range(self.num_randomly_moving_objects):
            self.r_objs.append(RandomlyMovingObject(boundary=self.boundary))

        self.viewable_objects = [self.tag] + self.r_objs

        self.object_universe.add_camera(self.camera).\
                             add_viewable_objects(self.viewable_objects)

        for timestamp in range(self.num_timestamps):
            self.camera.set_state_of_pan_motor_angle_at_timestamp(0, timestamp)

        self.camera.get_computer_vision().set_cv_ids_for_all_camera_time()

        self.base_position_calibrator = BasePositionCalibrator(
            self.camera,
            self.tag,
            tag_gps_angle_threshold=self.tag_gps_angle_threshold)

        return self

    def test_get_all_circumcircle_objects_gets_only_cc_objects(self):
        # Wrote this test while tracking down a bug which seems to be in ObjectPositionAnalyzer but which I discovered
        # when testing BaseAngleCalibrator. But I cant reproduce it here or in TestObjectMotionAnalyzer
        ccs = self.base_position_calibrator._get_all_circumcircle_objects()
        self.assertGreater(len(ccs), 0)
        for cc in ccs:
            self.assertEqual(type(cc), Circumcircles)

    def test_tag_candidate_is_always_the_tag(self):
        self.assertEqual(self.tag,
                         self.base_position_calibrator.get_tag_candidate())

    def test_get_base_position_returns_close_to_actual_base_position(self):
        cbp = self.base_position_calibrator.get_base_position()
        abp = self.camera.get_actual_position()

        self.assertEqual(type(cbp), tuple)
        self.assertEqual(type(abp), tuple)

        for i, _ in enumerate(cbp):
            self.assertAlmostEqual(cbp[i], abp[i], places=4)

    def test_get_intersection_points_returns_a_multipoint(self):
        points = self.base_position_calibrator._get_points_where_error_circle_intersections_intersect_each_other(
        )
        self.assertGreater(len(points), 0)
        self.assertEqual(type(points), MultiPoint)

    def test_all_error_circle_intersections_interesect_each_other(self):
        intersections = self.base_position_calibrator.get_all_error_circle_intersections(
        )
        for a in intersections:
            for b in intersections:
                self.assertTrue(a.intersects(b))

    def test_get_all_error_circle_intersections_gets_a_list_of_linestrings(
            self):
        intersections = self.base_position_calibrator.get_all_error_circle_intersections(
        )
        self.assertGreater(len(intersections), 0)
        for isect in intersections:
            self.assertEqual(type(isect), LineString)

    def test_get_all_circumcircle_objects_returns_circumcircle_objects_for_the_tag(
            self):
        ccs = self.base_position_calibrator._get_all_circumcircle_objects()
        self.assertGreater(len(ccs), 0)
        for cc in ccs:
            self.assertEqual(type(cc), Circumcircles)

    def visualize(self):

        renderable_objects = [
            self.boundary,
            self.object_universe,
            self.base_position_calibrator,
        ]

        RenderOrchestrator(self.num_timestamps,
                           seconds_per_timestamp=0.2,
                           renderable_objects=renderable_objects).run()
class TestComputerVision(unittest.TestCase):

    def setUp(self):
        self.num_timestamps = 6
        self.object_universe = ObjectUniverse(num_timestamps=self.num_timestamps)
        self.camera = Camera(fov_deg=90, actual_position=(0,0))
        self.cv = ComputerVision()
        self.camera.set_computer_vision(self.cv)
        self.object_universe.add_camera(self.camera)

        for timestamp, _ in enumerate(self.camera.get_state_history()):
            self.camera.set_pan_angle_deg(0, timestamp)

        self.out_pos = (1,2)
        self.in_pos = (1,0)

        self.out_obj = ViewableObject()
        self.in_obj = ViewableObject()
        self.in_out_in_obj = ViewableObject()
        self.out_in_out_obj = ViewableObject()

        self.viewable_objects = [
            self.out_obj,
            self.in_obj,
            self.in_out_in_obj,
            self.out_in_out_obj,
        ]

        self.object_universe.add_viewable_objects(self.viewable_objects)

        for timestamp, _ in enumerate(self.out_obj.position_history):
            self.in_obj.set_position_at_timestamp(self.in_pos, timestamp)
            self.out_obj.set_position_at_timestamp(self.out_pos, timestamp)

        for timestamp in [0,1]:
            self.in_out_in_obj.set_position_at_timestamp(self.in_pos, timestamp)
            self.out_in_out_obj.set_position_at_timestamp(self.out_pos, timestamp)

        for timestamp in [2,3]:
            self.in_out_in_obj.set_position_at_timestamp(self.out_pos, timestamp)
            self.out_in_out_obj.set_position_at_timestamp(self.in_pos, timestamp)

        for timestamp in [4,5]:
            self.in_out_in_obj.set_position_at_timestamp(self.in_pos, timestamp)
            self.out_in_out_obj.set_position_at_timestamp(self.out_pos, timestamp)

        self.cv.set_cv_ids_for_all_camera_time()

    def test_camera_has_correct_number_of_timestamps(self):
        self.assertEqual(self.camera.get_num_timestamps(), self.num_timestamps)
        self.assertEqual(self.camera.get_state_history_len(), self.num_timestamps)

    def test_viewable_objects_have_correct_number_of_timestamps(self):
        for vo in self.viewable_objects:
            self.assertEqual(vo.get_position_history_len(), self.num_timestamps)
            self.assertEqual(vo.get_num_timestamps(), self.num_timestamps)

    def test_objects_that_never_are_in_view_never_get_id(self):
        for timestamp, _ in enumerate(self.out_obj.get_position_history()):
            self.assertIsNone(self.cv.get_cv_id_for_obj_at_timestamp(self.out_obj, timestamp))

    def test_it_ids_objects_that_come_into_view(self):
        for timestamp in [0,1]:
            self.assertIsNone(self.cv.get_cv_id_for_obj_at_timestamp(self.out_in_out_obj, timestamp))
            self.assertIsNotNone(self.cv.get_cv_id_for_obj_at_timestamp(self.in_out_in_obj, timestamp))

        self.assertEqual(self.cv.get_cv_id_for_obj_at_timestamp(self.in_out_in_obj, 0),
                         self.cv.get_cv_id_for_obj_at_timestamp(self.in_out_in_obj, 1))

    def that_it_prefixes_the_ids_with_cv(self):
        self.assertEqual(self.cv.get_cv_id_for_obj_at_timestamp(self.in_obj,0)[0:2], 'cv')

    def test_it_retains_ids_of_objects_that_remain_in_view(self):
        self.assertEqual(self.cv.get_cv_id_for_obj_at_timestamp(self.out_in_out_obj, 2),
                         self.cv.get_cv_id_for_obj_at_timestamp(self.out_in_out_obj, 3))


    def test_it_removes_ids_of_objects_that_leave_view(self):
        self.assertIsNone(self.cv.get_cv_id_for_obj_at_timestamp(self.out_in_out_obj, 4))
        self.assertIsNone(self.cv.get_cv_id_for_obj_at_timestamp(self.out_in_out_obj, 5))

    def test_it_re_ids_objects_that_come_back_in_view(self):
        in_first = self.cv.get_cv_id_for_obj_at_timestamp(self.in_out_in_obj, 1)
        in_again = self.cv.get_cv_id_for_obj_at_timestamp(self.in_out_in_obj, 4)
        self.assertIsNotNone(in_first)
        self.assertIsNotNone(in_again)
        self.assertNotEqual(in_first, in_again)