def test_get_target_gps_location(self): self.test_drone_gps_location = Location(0,0,100) self.test_image_midpoint = (100,100) self.test_target_midpoint = (50,50) self.difference_vector = ((self.test_target_midpoint[0] - self.test_image_midpoint[0]) / math.sqrt(GCSSettings.IMAGE_PROC_PPSI) / 12, (self.test_target_midpoint[1] - self.test_image_midpoint[1]) / math.sqrt(GCSSettings.IMAGE_PROC_PPSI) / 12, 0) self.assertEqual(round(inverse_haversine(self.test_drone_gps_location, self.difference_vector).get_lat()), round(get_target_gps_location(self.test_image_midpoint, self.test_target_midpoint, self.test_drone_gps_location).get_lat())) self.test_drone_gps_location = Location(1000,1000,5) self.test_image_midpoint = (40,75) self.test_target_midpoint = (1000,510) self.difference_vector = ((self.test_target_midpoint[0] - self.test_image_midpoint[0]) / math.sqrt(GCSSettings.IMAGE_PROC_PPSI) / 12, (self.test_target_midpoint[1] - self.test_image_midpoint[1]) / math.sqrt(GCSSettings.IMAGE_PROC_PPSI) / 12, 0) self.assertEqual(round(inverse_haversine(self.test_drone_gps_location, self.difference_vector).get_lat()), round(get_target_gps_location(self.test_image_midpoint, self.test_target_midpoint, self.test_drone_gps_location).get_lat()))
def get_location(vehicle): """ Convert the vehicle's current location to a Location object :param vehicle: The vehicle to convert """ latitude = vehicle.location.global_relative_frame.lat longitude = vehicle.location.global_relative_frame.lon altitude = vehicle.location.global_relative_frame.alt * 3.28084 return Location(latitude, longitude, altitude)
def get_obstacle_location(obstacle, MSL_ALT): """ Get an Obstacle's location :param obstacle: The obstacle to convert :type obstacle: StationaryObstacle or MovingObstacle """ latitude = obstacle.latitude longitude = obstacle.longitude if isinstance(obstacle, interop.StationaryObstacle): altitude = obstacle.cylinder_height else: altitude = obstacle.altitude_msl + obstacle.sphere_radius - MSL_ALT return Location(latitude, longitude, altitude)
def inverse_haversine(location1, point): """ Calculate a second GPS point through using a single GPS point and a different in XY units :param location1: The first GPS coordinate :type location1: Location :param point: The point in the map that the obstacle occupies :type point: Numpy Array """ dy = point[1] / (3.28084 * 1000) dx = point[0] / (3.28084 * 1000) lat = location1.get_lat() + (dy / 111.195) lon = location1.get_lon() + ( dx / (math.cos(math.radians( (lat + location1.get_lat()) / 2.0)) * 111.191)) alt = point[2] / 3.28084 return Location(lat, lon, alt)
def autonomous_image_processing(): TARGET_MAP_PATH = "../../scripts/gcs/static/auto_imgs/" AUTONOMOUS_IMAGE_PROCESSING_SAVE_PATH = "../../scripts/gcs/static/auto_crops/" SAVE_PATH_FOR_POSTING = "static/auto_crops/" processed_target_maps = [] while True: sleep(1) try: map_list_response = requests.get("http://localhost:5000/get/imgs") target_map_list = map_list_response.json() needs_refresh = False except: continue interop_response = requests.get("http://localhost:5000/get/interop") interop_json = interop_response.json() fly_zones = construct_fly_zone_polygon_from_json(interop_json) runway_zone, runway_grass1_zone, runway_grass2_zone, runway_grass3_zone, runway_grass4_zone, runway_grass5_zone = construct_runway_fly_zone(): location_log_response = requests.get("http://localhost:5000/get/uav_location_log") location_log = location_log_response.json()["location_log"] for map_index in range(len(target_map_list)): if target_map_list[str(map_index)] in processed_target_maps: if map_index + 1 == len(target_map_list): needs_refresh = True continue else: current_target_map_name = target_map_list[str(map_index)] processed_target_maps.append(current_target_map_name) break if len(target_map_list) == 0 or needs_refresh: continue current_target_map_path = os.path.join(TARGET_MAP_PATH, current_target_map_name) combo_target_detection_result_list = SingleTargetMapDetector.detect_single_target_map(current_target_map_path) single_target_crops = combo_target_detection_result_list[0] json_file = combo_target_detection_result_list[1] image = Image.open(current_target_map_path) json_file["target_map_center_location"] = (image.width / 2, image.height / 2) json_file["target_map_timestamp"] = get_image_timestamp_from_metadata(current_target_map_path) print("Identifying targets within %s" % current_target_map_name) for index_in_single_target_crops in range(len(single_target_crops)): json_file["image_processing_results"][index_in_single_target_crops]["target_index"] = index_in_single_target_crops + 1 current_crop_path = os.path.join(AUTONOMOUS_IMAGE_PROCESSING_SAVE_PATH, current_target_map_name + " - " + str(index_in_single_target_crops + 1) + ".png") single_target_crops[index_in_single_target_crops].save(current_crop_path) # adds target location target_map_center_pixel_coordinates = json_file["target_map_center_location"] target_pixel_coordinates = json_file["image_processing_results"][index_in_single_target_crops]["target_location"] target_time = json_file["target_map_timestamp"] closest_time_index = 0 least_time_difference = location_log[0]["epoch_time"] for index in range(len(location_log)): difference_in_times = abs(target_time - location_log[closest_time_index]["epoch_time"]) if difference_in_times <= least_time_difference: closest_time_index = index least_time_difference = difference_in_times drone_gps_location = Location(location_log[closest_time_index]["latitude"], location_log[closest_time_index]["longitude"], location_log[closest_time_index]["altitude"]) target_location = get_target_gps_location(target_map_center_pixel_coordinates, target_pixel_coordinates, drone_gps_location) # check if target is in fly zones if fly_zones.contains_point([target_location.get_lat(), target_location.get_lon()]) == 0: print("target eleminated -- not in range") continue # check if target is in runway or runway grass. if on runway, eleminate, if on grass, do not eleminate if runway_zone.contains_point([drone_gps_location.get_lat(), drone_gps_location.get_lon()]): # target in runway zone -- check if on grass if runway_grass1_zone.contains_point([drone_gps_location.get_lat(), drone_gps_location.get_lon()]): pass elif runway_grass2_zone.contains_point([drone_gps_location.get_lat(), drone_gps_location.get_lon()]): pass elif runway_grass3_zone.contains_point([drone_gps_location.get_lat(), drone_gps_location.get_lon()]): pass elif runway_grass4_zone.contains_point([drone_gps_location.get_lat(), drone_gps_location.get_lon()]): pass elif runway_grass5_zone.contains_point([drone_gps_location.get_lat(), drone_gps_location.get_lon()]): pass else: # target not in grass; must be on runway -- eleminate continue json_file["image_processing_results"][index_in_single_target_crops]["latitude"] = target_location.get_lat() json_file["image_processing_results"][index_in_single_target_crops]["longitude"] = target_location.get_lon() shape_type = ShapeDetection.ShapeClassificationTwo(current_crop_path).get_shape_type() json_file["image_processing_results"][index_in_single_target_crops]["target_shape_type"] = shape_type color_classifying_results = Classifiers.ColorClassifier(current_crop_path).get_color() shape_color = color_classifying_results[0] letter_color = color_classifying_results[1] letter = "a" orientation = random.choice(["n","ne","e","se","s","sw","w","nw"]) json_file["image_processing_results"][index_in_single_target_crops]["target_shape_color"] = shape_color json_file["image_processing_results"][index_in_single_target_crops]["target_letter_color"] = letter_color json_file["image_processing_results"][index_in_single_target_crops]["target_orientation"] = orientation json_file["image_processing_results"][index_in_single_target_crops]["target_letter"] = letter # create the specific target post posting_json = {} posting_json["target"] = [] posting_json["target"].append({ "target_shape_color": shape_color, "target_letter_color": letter_color, "target_shape_type": shape_type, "target_orientation": orientation, "target_letter": letter, "latitude": target_location.get_lat(), "longitude": target_location.get_lon(), "current_crop_path": os.path.join(SAVE_PATH_FOR_POSTING, current_target_map_name + " - " + str(index_in_single_target_crops + 1) + ".png") }) requests.post("http://localhost:5000/post/autonomous_img_proc_target", json=posting_json) print("posted a %s %s" % (shape_color, shape_type)) with open(os.path.join(AUTONOMOUS_IMAGE_PROCESSING_SAVE_PATH, current_target_map_name[:-4] + ".json"), 'w') as fp: json.dump(json_file, fp, indent=4)
def load_sd_card(location_log, interop_client_array): SD_PATH = os.path.join("/Volumes", GCSSettings.SD_CARD_NAME, "DCIM") while True: print("Waiting SD Card to load...") if os.path.exists(SD_PATH): break sleep(5) print("SD Card loaded") if os.path.exists("static/all_imgs"): shutil.rmtree("static/all_imgs") os.makedirs("static/all_imgs") if os.path.exists("static/imgs"): shutil.rmtree("static/imgs") os.makedirs("static/imgs") if os.path.exists("static/crops"): shutil.rmtree("static/crops") os.makedirs("static/crops") if os.path.exists("static/autonomous_crops"): shutil.rmtree("static/autonomous_crops") os.makedirs("static/autonomous_crops") fly_zones = construct_fly_zone_polygon(interop_client_array) for pic_folder in os.listdir(SD_PATH): if not "." in pic_folder: pictures_dir_path = os.path.join(SD_PATH, pic_folder) for pic_name in os.listdir(pictures_dir_path): if ".jpg" in pic_name.lower() and pic_name[:1] != ".": pic_path = os.path.join(pictures_dir_path, pic_name) shutil.copy2(pic_path, "static/all_imgs") target_time = get_image_timestamp_from_metadata(pic_path) closest_time_index = 0 least_time_difference = location_log[0]["epoch_time"] for index in range(len(location_log)): difference_in_times = target_time - location_log[ closest_time_index]["epoch_time"] if abs(difference_in_times) <= least_time_difference: closest_time_index = index least_time_difference = difference_in_times drone_gps_location = Location( location_log[closest_time_index]["latitude"], location_log[closest_time_index]["longitude"], location_log[closest_time_index]["altitude"]) if fly_zones.contains_point([ drone_gps_location.get_lat(), drone_gps_location.get_lon() ]) == 0: # not in range continue shutil.copy2(pic_path, "static/imgs")
def test_submit_position(self): """ Test POST of position data """ self.interop_client.post_telemetry(Location(38, 76, 100), 350.0)
def load_sd_card(location_log, interop_client_array): SD_PATH = os.path.join("/Volumes", GCSSettings.SD_CARD_NAME, "DCIM") print("Waiting SD Card to load...") if os.path.exists("static/all_imgs"): shutil.rmtree("static/all_imgs") os.makedirs("static/all_imgs") if os.path.exists("static/imgs"): shutil.rmtree("static/imgs") os.makedirs("static/imgs") if os.path.exists("static/crops"): shutil.rmtree("static/crops") os.makedirs("static/crops") if os.path.exists("static/auto_crops"): shutil.rmtree("static/auto_crops") os.makedirs("static/auto_crops") if os.path.exists("static/auto_imgs"): shutil.rmtree("static/auto_imgs") os.makedirs("static/auto_imgs") print("Cleared Image Processing folders") while True: if os.path.exists(SD_PATH): break sleep(5) print("SD Card loaded") fly_zones = construct_fly_zone_polygon(interop_client_array) for pic_folder in os.listdir(SD_PATH): if not "." in pic_folder: pictures_dir_path = os.path.join(SD_PATH, pic_folder) for pic_name in os.listdir(pictures_dir_path): if ".jpg" in pic_name.lower() and pic_name[:1] != ".": pic_path = os.path.join(pictures_dir_path, pic_name) shutil.copy2(pic_path, "static/all_imgs") target_time = get_image_timestamp_from_metadata(pic_path) closest_time_index = 0 least_time_difference = location_log[0]["epoch_time"] for index in range(len(location_log)): difference_in_times = target_time - location_log[index]["epoch_time"] if abs(difference_in_times) <= least_time_difference: closest_time_index = index least_time_difference = difference_in_times drone_gps_location = Location(location_log[closest_time_index]["latitude"], location_log[closest_time_index]["longitude"], location_log[closest_time_index]["altitude"]) """ if not fly_zones.contains_point([drone_gps_location.get_lat(), drone_gps_location.get_lon()]): # not in designated flyzone from interop -- eleminate print(pic_name) print(drone_gps_location.get_lat()) print(drone_gps_location.get_lon()) print("is eleminated for not being in range") continue """ if abs(drone_gps_location.get_alt() - GCSSettings.SEARCH_AREA_ALT) > 30: # drone too low -- eliminate print(pic_name + " is eleminated for being too low or too high at " + str(drone_gps_location.get_alt()) + " ft") continue shutil.copy2(pic_path, "static/auto_imgs") shutil.copy2(pic_path, "static/imgs") print(pic_name + " accepted at " + str(drone_gps_location.get_alt()) + " ft")
def get_location(self): """ Return the VehicleState object's location """ return Location(self.get_lat(), self.get_lon(), self.get_alt())
def autonomous_image_processing(): TARGET_MAP_PATH = "static/imgs/" AUTONOMOUS_IMAGE_PROCESSING_SAVE_PATH = "static/autonomous_crops" processed_target_maps = [] while True: sleep(1) try: map_list_response = requests.get("http://localhost:5000/get/imgs") target_map_list = map_list_response.json() except: continue interop_response = requests.get("http://localhost:5000/get/interop") interop_json = interop_response.json() fly_zones = construct_fly_zone_polygon_from_json(interop_json) location_log_response = requests.get( "http://localhost:5000/get/uav_location_log") location_log = location_log_response.json()["location_log"] for map_index in range(len(target_map_list)): if not target_map_list[str(map_index)] in processed_target_maps: current_target_map_name = target_map_list[str(map_index)] processed_target_maps.append(current_target_map_name) break current_target_map_path = os.path.join(TARGET_MAP_PATH, current_target_map_name) combo_target_detection_result_list = SingleTargetMapDetector.detect_single_target_map( current_target_map_path) single_target_crops = combo_target_detection_result_list[0] json_file = combo_target_detection_result_list[1] image = Image.open(current_target_map_path) json_file["target_map_center_location"] = (image.width / 2, image.height / 2) json_file["target_map_timestamp"] = get_image_timestamp_from_metadata( current_target_map_path) for index_in_single_target_crops in range(len(single_target_crops)): json_file["image_processing_results"][ index_in_single_target_crops][ "target_index"] = index_in_single_target_crops + 1 current_crop_path = os.path.join( AUTONOMOUS_IMAGE_PROCESSING_SAVE_PATH, current_target_map_name + " - " + str(index_in_single_target_crops + 1) + ".png") single_target_crops[index_in_single_target_crops].save( current_crop_path) # adds target location target_map_center_pixel_coordinates = json_file[ "target_map_center_location"] target_pixel_coordinates = json_file["image_processing_results"][ index_in_single_target_crops]["target_location"] target_time = json_file["target_map_timestamp"] closest_time_index = 0 least_time_difference = location_log[0]["epoch_time"] for index in range(len(location_log)): difference_in_times = abs( target_time - location_log[closest_time_index]["epoch_time"]) if difference_in_times <= least_time_difference: closest_time_index = index least_time_difference = difference_in_times drone_gps_location = Location( location_log[closest_time_index]["latitude"], location_log[closest_time_index]["longitude"], location_log[closest_time_index]["altitude"]) target_location = get_target_gps_location( target_map_center_pixel_coordinates, target_pixel_coordinates, drone_gps_location) if fly_zones.contains_point( [target_location.get_lat(), target_location.get_lon()]) == 0: # not in range continue json_file["image_processing_results"][ index_in_single_target_crops][ "latitude"] = target_location.get_lat() json_file["image_processing_results"][ index_in_single_target_crops][ "longitude"] = target_location.get_lon() shape_type = ShapeDetection.ShapeClassificationTwo( current_crop_path).get_shape_type() json_file["image_processing_results"][ index_in_single_target_crops]["target_shape_type"] = shape_type color_classifying_results = Classifiers.ColorClassifier( current_crop_path).get_color() shape_color = color_classifying_results[0] letter_color = color_classifying_results[1] letter = "a" orientation = random.choice( ["n", "ne", "e", "se", "s", "sw", "w", "nw"]) json_file["image_processing_results"][ index_in_single_target_crops][ "target_shape_color"] = shape_color json_file["image_processing_results"][ index_in_single_target_crops][ "target_letter_color"] = letter_color json_file["image_processing_results"][ index_in_single_target_crops][ "target_orientation"] = orientation json_file["image_processing_results"][ index_in_single_target_crops]["target_letter"] = letter # create the specific target post posting_json = {} posting_json["target"] = [] posting_json["target"].append({ "target_shape_color": shape_color, "target_letter_color": letter_color, "target_shape_type": shape_type, "target_orientation": orientation, "target_letter": letter, "latitude": target_location.get_lat(), "longitude": target_location.get_lon(), "current_crop_path": current_crop_path }) requests.post( "http://localhost:5000/post/autonomous_img_proc_target", json=posting_json) with open( os.path.join(AUTONOMOUS_IMAGE_PROCESSING_SAVE_PATH, current_target_map_name[:-4] + ".json"), 'w') as fp: json.dump(json_file, fp, indent=4)