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
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])
def setUp(self): self.initial_num_timestamps = 100 self.boundary = Boundary([(0, 0), (100, 0), (100, 100), (0, 100)]) self.moving_object = RandomlyMovingObject( self.boundary, num_timestamps=self.initial_num_timestamps) self.stationary_object = StationaryObject( (100, 100), num_timestamps=self.initial_num_timestamps) self.viewable_objects = [self.moving_object, self.stationary_object] self.object_universe = ObjectUniverse()
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)
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 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 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
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()
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
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)
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 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
class TestObjectUniverse(unittest.TestCase): def setUp(self): self.initial_num_timestamps = 100 self.boundary = Boundary([(0, 0), (100, 0), (100, 100), (0, 100)]) self.moving_object = RandomlyMovingObject( self.boundary, num_timestamps=self.initial_num_timestamps) self.stationary_object = StationaryObject( (100, 100), num_timestamps=self.initial_num_timestamps) self.viewable_objects = [self.moving_object, self.stationary_object] self.object_universe = ObjectUniverse() def test_object_universe_has_correct_num_timestamps(self): self.assertEqual( self.object_universe.set_num_timestamps(50).get_num_timestamps(), 50) def test_viewable_objects_have_correct_num_initial_timestamps(self): for vo in self.viewable_objects: self.assertEqual(vo.get_position_history_len(), self.initial_num_timestamps) def test_viewable_objects_get_history_len_from_universe_they_are_addded_to( self): self.object_universe.set_num_timestamps(50).add_viewable_objects( self.viewable_objects) for vo in self.object_universe.get_viewable_objects(): self.assertEqual(vo.get_position_history_len(), 50) def test_changing_univererse_lifespan_changes_history_for_all_included_viewable_objects( self): self.object_universe.set_num_timestamps(50).add_viewable_objects( self.viewable_objects) self.object_universe.set_num_timestamps(1000) for vo in self.object_universe.get_viewable_objects(): self.assertEqual(vo.get_position_history_len(), 1000) def test_when_viewable_object_position_history_is_reduced_it_is_a_truncated_version_of_original_postion_history( self): self.object_universe.set_num_timestamps(50).add_viewable_objects( self.viewable_objects) for vo in self.object_universe.get_viewable_objects(): for timestamp in range(vo.get_num_timestamps()): self.assertIsNotNone(vo.get_position_at_timestamp(timestamp))
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 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)
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 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()
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()
def test_stationary_object_updates_its_num_timestamps_to_match_object_universe_it_gets_added_to(self): ou = ObjectUniverse(num_timestamps=200) ou.add_viewable_objects(self.so) self.assertEqual(self.so.get_position_history_len(), 200) for timestamp in range(0, 200): self.assertEqual(self.so.get_position_at_timestamp(timestamp), self.pos)
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)