Source code for DroneProject.MapViewApp

# -*- coding: UTF-8 -*-


#Name:        James Hall
#Student No.: C00007006
#Institute:   Institute of Technology Carlow
#Project:     Drone Traffic Control System     
#Date:        April 2021 
#License:     GNU Affero General Public License v3.0

#Main App Screen and Layers

"""
MapViewApp.py
=================================

This is the core module for the ADTCS project
"""
import os
import random
from math import *
from kivy.garden.mapview.mapview.utils import clamp
import time
import pickle
import threading
from DroneController import *
from AbstractDrone import AbstractDrone
from VirtualDrone import VirtualDrone
from Location import Location
from Flight import Flight
from save_load import *
from PrintLists import *
from FloatInput import FloatInput

from kivy.config import Config
Config.set('graphics','maxfps','60')
from kivy.lang import Builder

from kivy.uix.behaviors.focus import FocusBehavior
from kivy.uix.screenmanager import ScreenManager, Screen

from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.popup import Popup
from kivy.uix.image import Image
from kivy.properties import ObjectProperty, NumericProperty, StringProperty, BooleanProperty
from kivy.uix.recycleview import RecycleView
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window

from kivy.app import App
from kivy.clock import Clock
from kivy.graphics import Color, Line
from kivy.graphics.transformation import Matrix
from kivy.graphics.context_instructions import Translate, Scale
from kivy.garden.mapview.mapview import MapView, MapLayer, MapMarker, MarkerMapLayer, MIN_LONGITUDE, MIN_LATITUDE, MAX_LATITUDE, MAX_LONGITUDE

from functools import partial

drones = LoadDroneList()
locations = LoadLocationList()
flights = LoadFlightList()
threads = []      
coordinates = []
corridors = []
network = []
drone_hidden = True
location_hidden = True
new_location_add = False
name = ''
location_layer = None
 
[docs]class MapViewApp(App): """ Main App Class """ mapview = None def __init__(self, **kwargs): super(MapViewApp, self).__init__(**kwargs) Clock.schedule_once(self.post, 0)
[docs] def build(self): self.title = "Drone Air Traffic Control" layout = BoxLayout(orientation='vertical') return layout
[docs] def post(self, *args): global location_layer layout = FloatLayout() self.mapview = MapView(zoom=18, lat=52.824725, lon=-6.935661) line = LineMapLayer() self.mapview.add_layer(line, mode="scatter") # window scatter drone_layer = DroneMarkerLayer() self.mapview.add_layer(drone_layer, mode="scatter") location_layer = LocationMarkerLayer() self.mapview.add_layer(location_layer, mode="scatter") flights_layer = FlightLayer() self.mapview.add_layer(flights_layer, mode="scatter") layout.add_widget(self.mapview) dronebuttoncolor = [.3,1,0,1] #Green locationbuttoncolor = [.5,1,1,1] #Blue flightbuttoncolor = [1,1,.5,1] #Yellow #Button containers buttonrow1 = BoxLayout(orientation='horizontal',height='30dp',size_hint_y=None) buttonrow2 = BoxLayout(orientation='horizontal',height='30dp',size_hint_y=None) buttonrow3 = BoxLayout(orientation='horizontal',height='30dp',size_hint_y=None) buttonrow1.add_widget(Button(text="RemoveDrone",on_press=lambda a: drone_layer.remove_drone_popup(), background_color = dronebuttoncolor)) buttonrow1.add_widget(Button(text="AddDrone",on_press=lambda a: drone_layer.add_virtual_drone_popup(), background_color = dronebuttoncolor)) buttonrow1.add_widget(Button(text="ViewLocationsList",on_press=lambda a: location_layer.view_locations_popup(), background_color = locationbuttoncolor)) buttonrow1.add_widget(Button(text="ViewLocationMarkers", background_color = locationbuttoncolor, on_press=lambda a: show_locations_button(self.mapview, location_layer, drone_layer))) buttonrow2.add_widget(Button(text="ViewDrones", background_color = dronebuttoncolor,on_press=lambda a: show_drones_button(self.mapview, drone_layer, location_layer))) buttonrow2.add_widget(Button(text="AddVirtualDrone",on_press=lambda a: drone_layer.add_virtual_drone_popup(), background_color = dronebuttoncolor)) buttonrow2.add_widget(Button(text="AddLocation",on_press=lambda a: location_layer.add_point_popup(), background_color = locationbuttoncolor)) buttonrow2.add_widget(Button(text="RemoveLocation",on_press=lambda a: location_layer.remove_location_popup(), background_color = locationbuttoncolor)) buttonrow3.add_widget(Button(text="ViewFlightsList",on_press=lambda a: flights_layer.view_flights_popup(), background_color = flightbuttoncolor)) buttonrow3.add_widget(Button(text="CreateFlight",on_press=lambda a: flights_layer.create_flight_popup(), background_color = flightbuttoncolor)) buttonrow3.add_widget(Button(text="RemoveFlight",on_press=lambda a: flights_layer.remove_flight_popup(), background_color = flightbuttoncolor)) buttonrow3.add_widget(Button(text="StartFlight",on_press=lambda a: flights_layer.start_flight_popup(), background_color = flightbuttoncolor)) buttonrow3.add_widget(Button(text="AbortFlight",on_press=lambda a: flights_layer.abort_flight_popup(), background_color = flightbuttoncolor)) #First button row self.root.add_widget(buttonrow1) #Second button row self.root.add_widget(buttonrow2) #Third button row self.root.add_widget(buttonrow3) self.root.add_widget(layout) #Used to draw locationmarkers on screen def show_locations_button(mapview, locationslayer, droneslayer): global location_hidden global drone_hidden global threads mapv = mapview locationsl = locationslayer dronesl = droneslayer if location_hidden == True: location_hidden = False locationsl.draw_locations() elif location_hidden == False: location_hidden = True for child in mapv.children: if type(child) is MarkerMapLayer: #Remove all marker widgets and add back in Drone markers if not hidden child.clear_widgets() if drone_hidden == False: threads.append(Thread(target = dronesl.draw_drones, args = (dronesl, locationsl), daemon = True)) threads[len(threads)-1].start() break #Used to draw drone markers on screen def show_drones_button(mapview, droneslayer, locationslayer): global drone_hidden global location_hidden global threads mapv = mapview dronesl = droneslayer locationsl = locationslayer if drone_hidden == True: drone_hidden = False threads.append(Thread(target = dronesl.draw_drones, args = (dronesl, locationsl), daemon = True)) threads[len(threads)-1].start() elif drone_hidden == False: drone_hidden = True for child in mapv.children: if type(child) is MarkerMapLayer: #Remove all marker widgets and add back in Location markers if not hidden child.clear_widgets() if location_hidden == False: locationsl.draw_locations() break
###Class related to CRUD location operations
[docs]class LocationMarkerLayer(MapLayer): """ Class for adding Location and Location Markers """ locationview = None def __init__(self, **kwargs): super(LocationMarkerLayer, self).__init__(**kwargs) self.zoom = 0 locationview = self.parent
[docs] def on_touch_down(self, touch): """ Adds functionality to kivy's on_touch_down() event, specificly for adding new Locations """ global new_location_add global location_layer if new_location_add == True: print(touch.pos[0]) print(touch.pos[1]) location_layer.add_point(touch.pos[0],touch.pos[1],0) return super(LocationMarkerLayer, self).on_touch_down(touch)
[docs] def draw_locations(self, *args): """ Adds location markers to MapLayer """ locationview = self.parent self.zoom = locationview.zoom global locations for location in locations: # Draw new Location markers locationview.add_marker(MapMarker(lat=location.getlocationlatitude(), lon=location.getlocationlongitude(), source='images/MapMarker.png'))
[docs] def add_point(self, lat, lon, alt): """ Adds a location to system """ global locations global new_location_add global name if new_location_add == True: newlocation = Location(name, self.parent.get_latlon_at(lat,lon)[0], self.parent.get_latlon_at(lat,lon)[1], alt) new_location_add = False #: Add a point a chosen coordinates print("location to add:") print (newlocation.getlocationname()) locations.append(newlocation) self.draw_locations() SaveLocationList(locations)
[docs] def set_loc_name(self, nname): """ Set name for new location to be added to system """ global name global new_location_add name = nname new_location_add = True
[docs] def add_point_popup(self): """ Popup used to set name for new location """ mapview = self.parent global locations global name global new_location_add self.root = BoxLayout(orientation='vertical',spacing=15) nameinput = TextInput(hint_text="name", multiline=False, size_hint=(.9, None), pos_hint ={'center_x': .5,'center_y': 1}, height=40) self.root.add_widget(nameinput, index=0) self.popup = Popup(title="Add Location", auto_dismiss=True, size_hint=(.5,.5)) self.root.add_widget(Button(text="Add Location Name", size_hint=(.9,.7), pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: (self.popup.dismiss(),self.set_loc_name(nameinput.text)))) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1], size_hint=(.9,.7), pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: self.popup.dismiss())) self.popup.add_widget(self.root) self.popup.open()
[docs] def view_locations_popup(self): """ Popup to display a list of locations on system """ self.root = BoxLayout(orientation='vertical',spacing=15) #Scrollable location list locationlistview = Label(text= location_list(),size_hint=(1.01, None)) locationlistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/2),scroll_y=1, do_scroll_x=False, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) locationlistviewscroll.add_widget(locationlistview) locationlistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(locationlistviewscroll) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1], size_hint=(.9,.7), pos_hint ={'center_x': .5,'center_y': 1}, on_press=lambda a: self.popup.dismiss())) self.popup = Popup(title="View Location List", auto_dismiss=True, size_hint=(.9,.8)) self.popup.add_widget(self.root) self.popup.open()
[docs] def remove_location_popup(self): """ Popup used to remove location from system """ def buttonPressRemoveLocation(selection): global locations global drone_hidden global location_hidden global threads if int(selection) < 1 or int(selection) > len(locations): return del locations[int(selection)-1] SaveLocationList(locations) self.root = BoxLayout(orientation='vertical',spacing=15) locationlistview = Label(text= location_list(),size_hint=(1.01, None)) locationlistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/4),scroll_y=1, do_scroll_x=False, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) locationlistviewscroll.add_widget(locationlistview) locationlistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(locationlistviewscroll) location = FloatInput(hint_text="Enter Number corresponding to location", multiline=False, size_hint=(.9, None), pos_hint ={'center_x': .5,'center_y': 1},height=40) self.root.add_widget(location) self.root.add_widget(Button(text="RemoveLocation", size_hint=(.9,.8), pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: buttonPressRemoveLocation(location.text))) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1], size_hint=(.9,.8), pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: self.popup.dismiss())) #Add popup widget to root self.popup = Popup(title="Remove Location", auto_dismiss=True, size_hint=(.9,.8)) self.popup.add_widget(self.root) self.popup.open()
[docs]class DroneMarkerLayer(MapLayer): """ Class related to CRUD drones operations """ droneview = None def __init__(self, **kwargs): super(DroneMarkerLayer, self).__init__(**kwargs) self.zoom = 0 droneview = self.parent
[docs] def add_virtual_drone(self, name, home): """ Adds a virtual drone to the system """ global locations if int(home) <= len(locations): for location in locations: if location.getlocationname() == locations[int(home)-1].getlocationname(): home_loc = location global drones newdrone = VirtualDrone(name, "Virtual", float(home_loc.getlocationlatitude()), float(home_loc.getlocationlongitude()), float(home_loc.getlocationlatitude()), float(home_loc.getlocationlongitude()), 0, 100, 0, "Grounded", 0) break drones.append(newdrone) SaveDroneList(drones)
[docs] def add_virtual_drone_popup(self): """ Popup to add virtual drone to the system """ global drones global locations self.root = BoxLayout(orientation='vertical',spacing=15) nameinput = TextInput(hint_text="drone name", multiline=False,size_hint=(.9, None),pos_hint ={'center_x': .5,'center_y': 1},height=40) homeinput = FloatInput(hint_text="home location name", multiline=False,size_hint=(.9, None),pos_hint ={'center_x': .5,'center_y': 1},height=40) #Text boxes to add location info self.root.add_widget(nameinput, index=0) locationlistview = Label(text= location_list(),size_hint=(1, None)) locationlistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/4), do_scroll_x=False, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) locationlistviewscroll.add_widget(locationlistview) locationlistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(locationlistviewscroll) self.root.add_widget(homeinput, index=0) self.root.add_widget(Button(text="AddDrone",size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: self.add_virtual_drone(nameinput.text, homeinput.text))) self.popup = Popup(title="Add Drone", auto_dismiss=True, size_hint=(.9,.8)) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1],size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: self.popup.dismiss())) #Add popup widget to root self.popup.add_widget(self.root) self.popup.open()
[docs] def remove_drone_popup(self): """ Popup the remove a drone from the system """ def buttonPressRemoveDrone(selection): """ Function removes drone when button pressed """ global drones if int(selection) < 1 or int(selection) > len(drones): return del drones[int(selection)-1] SaveDroneList(drones) self.root = BoxLayout(orientation='vertical',spacing=15) #Scrollable Drone list dronelistview = Label(text= drone_list(),size_hint=(1.01, None)) dronelistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/4), do_scroll_x=False, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) dronelistviewscroll.add_widget(dronelistview) dronelistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(dronelistviewscroll) #Input box location = FloatInput(hint_text="Enter Number corresponding to drone", multiline=False, size_hint=(.9,None), pos_hint={'center_x': .5,'center_y': 1},height=40) self.root.add_widget(location) self.root.add_widget(Button(text="RemoveDrone", size_hint=(.9,.7), pos_hint={'center_x': .5,'center_y': 1},on_press=lambda a: buttonPressRemoveDrone(location.text))) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1], size_hint=(.9,.7), pos_hint={'center_x': .5,'center_y': 1},on_press=lambda a: self.popup.dismiss())) #Add popup widget to root self.popup = Popup(title="Remove Drone", auto_dismiss=True, size_hint=(.9,.8)) self.popup.add_widget(self.root) self.popup.open()
[docs] def insert_drone_image(self, drone, *largs): """ Used to choose suitable image for drawing drone marker on screen """ droneview = self.parent if drone.getdronestate() == "Descending" and drone.getbattery() > 50: droneview.add_marker(MapMarker(lat=drone.getcurrentlatitude(), lon=drone.getcurrentlongitude(), source="images/DroneDescending.png")) elif drone.getdronestate() == "Descending" and drone.getbattery() <= 50: droneview.add_marker(MapMarker(lat=drone.getcurrentlatitude(), lon=drone.getcurrentlongitude(), source="images/DroneDescending50batt.png")) elif drone.getdronestate() == "Descending" and drone.getbattery() <= 10: droneview.add_marker(MapMarker(lat=drone.getcurrentlatitude(), lon=drone.getcurrentlongitude(), source="images/DroneDescending10batt.png")) elif drone.getdronestate() == "Ascending" and drone.getbattery() > 50: droneview.add_marker(MapMarker(lat=drone.getcurrentlatitude(), lon=drone.getcurrentlongitude(), source="images/DroneAscending.png")) elif drone.getdronestate() == "Ascending" and drone.getbattery() <= 50: droneview.add_marker(MapMarker(lat=drone.getcurrentlatitude(), lon=drone.getcurrentlongitude(), source="images/DroneAscending50batt.png")) elif drone.getdronestate() == "Ascending" and drone.getbattery() <= 10: droneview.add_marker(MapMarker(lat=drone.getcurrentlatitude(), lon=drone.getcurrentlongitude(), source="images/DroneAscending10batt.png")) elif drone.getbattery() > 50: droneview.add_marker(MapMarker(lat=drone.getcurrentlatitude(), lon=drone.getcurrentlongitude(), source="images/Drone.png")) elif drone.getbattery() <= 50: droneview.add_marker(MapMarker(lat=drone.getcurrentlatitude(), lon=drone.getcurrentlongitude(), source="images/Drone50batt.png")) else: droneview.add_marker(MapMarker(lat=drone.getcurrentlatitude(), lon=drone.getcurrentlongitude(), source="images/Drone10batt.png"))
[docs] def draw_drones(self, dronel, locationl): """ Adds drone markers to MapLayer """ dronel = dronel locationl = locationl droneview = self.parent self.zoom = droneview.zoom global drones global drone_hidden global flights flightinprogress = False for drone in drones: if drone.getdronestate() != "Grounded": flightinprogress = True break i = 1 #Used to draw the drones once when not in flight while (drone_hidden == False and flightinprogress == True) or i == 1: for child in droneview.children: if type(child) is MarkerMapLayer: child.clear_widgets() break #Draw location markers if they should be seen if location_hidden == False: Clock.schedule_once(partial(locationl.draw_locations)) for drone in drones: #Draw Drone markers Clock.schedule_once(partial(self.insert_drone_image, drone)) time.sleep(.05) i = i+1
[docs]class FlightLayer(MapLayer): """ Class related to flight CRUD operations """ def __init__(self, **kwargs): super(FlightLayer, self).__init__(**kwargs) self.zoom = 0 droneview = self.parent
[docs] def view_flights_popup(self): """ Displays list of flights on system """ self.root = BoxLayout(orientation='vertical',spacing=15) flightlistview = Label(text= flight_list(),size_hint=(1.01, None)) flightlistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/2),scroll_y=1, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) flightlistviewscroll.add_widget(flightlistview) flightlistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(flightlistviewscroll) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1], size_hint=(.9,.7), pos_hint={'center_x': .5,'center_y': 1},on_press=lambda a: self.popup.dismiss())) self.popup = Popup(title="View Flight List", auto_dismiss=True, size_hint=(.9,.7)) self.popup.add_widget(self.root) self.popup.open()
[docs] def create_flight_popup(self): """ Popup used to add flights to the system """ mapview = self.parent global flights global locations global drones new_flight = Flight("F", 0, 0, 0, 0, "D", False, False) def buttonPressAddFlightName(newflight, name): newflight.setflightid(name) def buttonPressAddDrone(newflight, drones, selection): for drone in drones: if drone.drone_id == drones[int(selection)-1].drone_id: newflight.setdrone(drone.drone_id) newflight.setstartlatitude(drone.gethomelatitude()) newflight.setstartlongitude(drone.gethomelongitude()) def buttonPressAddDestination(newflight, locations, selection): for location in locations: if location.getlocationname() == locations[int(selection)-1].getlocationname(): newflight.setdestinationlatitude(location.getlocationlatitude()) newflight.setdestinationlongitude(location.getlocationlongitude()) #Adds Flight to system Flight list def buttonPressAddFlight(newflight, flights): flights.append(newflight) SaveFlightList(flights) self.popup.dismiss() self.root = BoxLayout(orientation='vertical', spacing =5) flightname = TextInput(hint_text="Flight Name", multiline=False,size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1}) self.root.add_widget(flightname) #Scrollable Drone list dronelistview = Label(text= drone_list(),size_hint=(1.01, None)) dronelistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/8), do_scroll_x=False, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) dronelistviewscroll.add_widget(dronelistview) dronelistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(dronelistviewscroll) drone = FloatInput(hint_text="Drone choice", multiline=False,size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1}) self.root.add_widget(drone) locationlistview = Label(text= location_list(),size_hint=(1.01, None)) locationlistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/8), do_scroll_x=False,scroll_y=1, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) locationlistviewscroll.add_widget(locationlistview) locationlistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(locationlistviewscroll) location = FloatInput(hint_text="Destination Choice", multiline=False,size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1}) self.root.add_widget(location) self.root.add_widget(Button(text="AddFlightName",size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: buttonPressAddFlightName(new_flight, flightname.text))) self.root.add_widget(Button(text="AddDrone",size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: buttonPressAddDrone(new_flight, drones, drone.text))) self.root.add_widget(Button(text="AddDestination",size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: buttonPressAddDestination(new_flight, locations, location.text))) self.root.add_widget(Button(text="AddFlight",size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: buttonPressAddFlight(new_flight, flights))) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1],size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: self.popup.dismiss())) self.popup = Popup(title="Add Flight", auto_dismiss=True, size_hint=(.9,.8)) self.popup.add_widget(self.root) self.popup.open()
[docs] def remove_flight_popup(self): """ Remove flight popup """ def buttonPressRemoveFlight(selection): """ Deletes flight from system on button press """ global flights if int(selection) <= len(flights): del flights[int(selection)-1] SaveFlightList(flights) self.root = BoxLayout(orientation='vertical',spacing=15) flightlistview = Label(text= flight_list(),size_hint=(1.01, None)) flightlistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/4),scroll_y=1, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) flightlistviewscroll.add_widget(flightlistview) flightlistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(flightlistviewscroll) flight = FloatInput(hint_text="Enter Number corresponding to flight", multiline=False, size_hint=(.9, None), pos_hint ={'center_x': .5,'center_y': 1}, height = 40) self.root.add_widget(flight) self.root.add_widget(Button(text="CancelFlight",size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: buttonPressRemoveFlight(flight.text))) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1],size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: self.popup.dismiss())) self.popup = Popup(title="Cancel Flight", auto_dismiss=True, size_hint=(.9,.8)) self.popup.add_widget(self.root) self.popup.open()
[docs] def abort_flight_popup(self): """ Abort flight popup """ def buttonPressAbortFlight(selection): """ Set flight parameter flight_abort to True, this will be checked by the DroneController.MoveDrone() function and the drone will be redirected """ global flights flights[int(selection)-1].setflightabort(True) SaveFlightList(flights) self.root = BoxLayout(orientation='vertical',spacing=15) #Scrollable list of flights flightlistview = Label(text= flight_list(),size_hint=(1.01, None)) flightlistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/4),scroll_y=1, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) flightlistviewscroll.add_widget(flightlistview) flightlistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(flightlistviewscroll) #Input Box flight = FloatInput(hint_text="Enter Number corresponding to flight", multiline=False, size_hint=(.9, None), pos_hint ={'center_x': .5,'center_y': 1},height=40) self.root.add_widget(flight) self.root.add_widget(Button(text="AbortFlight",size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: buttonPressAbortFlight(flight.text))) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1],size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: self.popup.dismiss())) self.popup = Popup(title="Abort Flight", auto_dismiss=True, size_hint=(.9,.8)) self.popup.add_widget(self.root) self.popup.open()
[docs] def start_flight_popup(self): """ Begin a flight popup """ def buttonPressBeginFlight(selection): """ Begins flight on button press """ global flights global locations global drones global threads if int(selection) <= len(flights): for drone in drones: if drone.drone_id == flights[int(selection)-1].getdrone(): flight_drone = drone threads.append(Thread(target = TakeOffFlyLand, args = (flight_drone, flights[int(selection)-1], drones, locations), daemon = True)) threads[len(threads)-1].start() self.root = BoxLayout(orientation='vertical',spacing=15) flightlistview = Label(text= flight_list(),size_hint=(1.01, None)) flightlistviewscroll = ScrollView(size_hint=(1, None), size=(Window.width, Window.height/4),scroll_y=1, scroll_type=['bars','content'], bar_width = 10, pos_hint ={'center_x': .5,'center_y': 1}) flightlistviewscroll.add_widget(flightlistview) flightlistviewscroll.effect_cls.spring_constant=0 self.root.add_widget(flightlistviewscroll) flight = FloatInput(hint_text="Enter Number corresponding to flight", multiline=False, size_hint=(.9, None), pos_hint ={'center_x': .5,'center_y': 1}, height = 40) self.root.add_widget(flight) self.root.add_widget(Button(text="BeginFlight",size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: buttonPressBeginFlight(flight.text))) self.root.add_widget(Button(text="Close window", background_color = [1,0,0,1],size_hint=(.9, .8),pos_hint ={'center_x': .5,'center_y': 1},on_press=lambda a: self.popup.dismiss())) self.popup = Popup(title="Start Flight", auto_dismiss=True, size_hint=(.9,.8)) self.popup.add_widget(self.root) self.popup.open()
[docs]class LineMapLayer(MapLayer): """ Class related to displaying lines between destinations !Currently incomplete """ def __init__(self, **kwargs): super(LineMapLayer, self).__init__(**kwargs) self.zoom = 0 mapview = self.parent global coordinates
[docs] def reposition(self): mapview = self.parent global corridors #: Must redraw when the zoom changes #: as the scatter transform resets for the new tiles if (self.zoom != mapview.zoom): self.draw_line()
[docs] def create_corridor_popup(self): mapview = self.parent global coordinates global locations global corridors corridortoadd = [] def buttonPressAddLocation(coord, corr, corridortoadd, selection): corridortoadd.append(coord[int(selection)-1]) print(coord[int(selection)-1]) print(corridortoadd) def buttonPressAddCorridor(corr): global corridors corridors.append(corridortoadd) #self.draw_line(corr) self.draw_line() print("Full corridors list:") print(corridors) self.root = BoxLayout(orientation='vertical', spacing =5) self.root.add_widget(Label(text= self.location_list())) location = TextInput(hint_text="Enter Number corresponding to flight", multiline=False) self.root.add_widget(location, index=0) self.root.add_widget(Label(text= str(corridortoadd))) self.root.add_widget(Button(text="AddLocation",on_press=lambda a: buttonPressAddLocation(coordinates, corridors, corridortoadd, location.text))) self.root.add_widget(Button(text="AddCorridor",on_press=lambda a: buttonPressAddCorridor(corridortoadd))) self.root.add_widget(Button(text="Close window",on_press=lambda a: self.popup.dismiss())) self.popup = Popup(title="Add Corridor", auto_dismiss=True, size_hint=(.5,.5)) self.popup.add_widget(self.root) self.popup.open()
[docs] def get_x(self, lon): """Get the x position on the map using this map source's projection (0, 0) is located at the top left. """ return clamp(lon, MIN_LONGITUDE, MAX_LONGITUDE)
[docs] def get_y(self, lat): """Get the y position on the map using this map source's projection (0, 0) is located at the top left. """ lat = clamp(-lat, MIN_LATITUDE, MAX_LATITUDE) lat = lat * pi / 180. return ((1.0 - log(tan(lat) + 1.0 / cos(lat)) / pi))
[docs] def draw_line(self, *args): mapview = self.parent self.zoom = mapview.zoom global coordinates global corridors #corridor = corr # When zooming we must undo the current scatter transform # or the animation distorts it scatter = mapview._scatter map_source = mapview.map_source sx,sy,ss = scatter.x, scatter.y, scatter.scale vx,vy,vs = mapview.viewport_pos[0], mapview.viewport_pos[1], mapview.scale # Account for map source tile size and mapview zoom ms = pow(2.0,mapview.zoom) * map_source.dp_tile_size #: Since lat is not a linear transform we must compute manually #line_points = [] with self.canvas: # Clear old line self.canvas.clear() for corridor in corridors: line_points = [] for lat,lon in corridor: line_points.extend((self.get_x(lon),self.get_y(lat))) print("linepointslist:") print (line_points) #line_points.extend(mapview.get_window_xy_from(lat,lon,mapview.zoom)) with self.canvas: # Clear old line #self.canvas.clear() # Undo the scatter animation transform Scale(1/ss,1/ss,1) Translate(-sx,-sy) # Apply the get window xy from transforms Scale(vs,vs,1) Translate(-vx,-vy) # Apply the what we can factor out # of the mapsource long,lat to x,y conversion Scale(ms/360.0,ms/2.0,1) Translate(180,0) # Draw new Color(1, 0, 0, 1) print("linepointslist Line:") print (line_points) Line(points=line_points, width=1)#4/ms)#, joint="round",joint_precision=100) self.canvas.ask_update()
if __name__ == "__main__": MapViewApp().run()