flockompass/main.py
2020-08-04 21:52:20 -05:00

191 lines
5.1 KiB
Python

from plyer import gps
from kivy.app import App
from kivy.clock import Clock
from kivy.properties import NumericProperty, StringProperty
from kivy.clock import mainthread
from kivy.utils import platform
from kivy.uix.screenmanager import ScreenManager, Screen, RiseInTransition
from kivy_garden.mapview import MapView
from kivy.vector import Vector
from kivy.animation import Animation
from math import floor
import random
from pprint import pprint
root = None
class MapScreen(Screen):
def choose_destination(self):
root.parent.dest_lat = self.ids.centermark.lat
root.parent.dest_lon = self.ids.centermark.lon
class CompassScreen(Screen):
x_calib = NumericProperty(0)
y_calib = NumericProperty(0)
z_calib = NumericProperty(0)
needle_angle = NumericProperty(0)
gps_location = StringProperty()
gps_status = StringProperty('Click Start to get GPS location updates')
def get_field(self, dt):
needle_angle = 7
if self.facade.field != (None, None, None):
self.x_calib, self.y_calib, self.z_calib = self.facade.field
x, y, z = self.facade.field
needle_angle = Vector(x, y).angle((0, 1)) + 90.
# fix animation transition around the unit circle
if (self.needle_angle % 360) - needle_angle > 180:
needle_angle += 360
elif (self.needle_angle % 360) - needle_angle < -180:
needle_angle -= 360
# add the number of revolutions to the result
needle_angle += 360 * floor(self.needle_angle / 360.)
# animate the needle
if self._anim:
self._anim.stop(self)
self._anim = Animation(needle_angle=needle_angle, d=.2, t='out_quad')
self._anim.start(self)
def sensors_start(self):
self.compass_enable()
self.gps_start(1000, 0)
def sensors_stop(self):
self.compass_disable()
self.gps_stop()
def compass_enable(self):
self.facade.enable()
Clock.schedule_interval(self.get_field, 1 / 5.0)
def compass_disable(self):
self.facade.disable()
Clock.unschedule(self.get_field)
def gps_start(self, minTime, minDistance):
gps.start(minTime, minDistance)
def gps_stop(self):
gps.stop()
def on_pause(self):
self.compass_disable()
self.gps_stop()
return True
def on_resume(self):
self.compass_enable()
self.gps_start(1000, 0)
@mainthread
def on_location(self, **kwargs):
self.parent.parent.lat = kwargs['lat']
self.parent.parent.lon = kwargs['lon']
# self.parent.speed = kwargs['speed']
# self.parent.bearing = kwargs['bearing']
# self.gps_location = '\n'.join([
# '{}={}'.format(k, v) for k, v in kwargs.items()])
# bearing = atan2(sin(long2-long1)*cos(lat2), cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(long2-long1))
# bearing = degrees(bearing)
# bearing = (bearing + 360) % 360
# https://stackoverflow.com/questions/4913349/haversine-formula-in-python-bearing-and-distance-between-two-gps-points#4913653
@mainthread
def on_status(self, stype, status):
self.gps_status = 'type={}\n{}'.format(stype, status)
class FlockompassApp(App):
lat = 19.3419
lon = -99.1499
dest_lat = 19.3429
dest_lon = -99.15
def move_around(self, t):
self.lat += random.uniform(-0.01,0.01)
self.lon += random.uniform(-0.01,0.01)
self.ms.ids.mapview.center_on(self.lat, self.lon)
# where the marker's at
def request_android_permissions(self):
from android.permissions import request_permissions, Permission
def callback(permissions, results):
if all([res for res in results]):
print("aguas: callback. All permissions granted.")
else:
print("aguas: callback. Some permissions refused.Permission.ACCESS_FINE_LOCATION")
request_permissions([Permission.ACCESS_COARSE_LOCATION,
Permission.ACCESS_FINE_LOCATION],
callback)
def build(self):
global root
root = ScreenManager(transition=RiseInTransition())
self.ms = MapScreen(name='map')
root.add_widget(self.ms)
cs = CompassScreen(name='compass')
cs._anim = None
cs.p = None
root.add_widget(cs)
if platform == "android":
print("gps.py: Android detected. Requesting permissions")
self.request_android_permissions()
try:
gps.configure(on_location=cs.on_location,
on_status=cs.on_status)
except NotImplementedError:
import traceback
traceback.print_exc()
print('GPS is not implemented for your platform')
Clock.schedule_interval(self.move_around, 7.0)
return root
if __name__ == '__main__':
FlockompassApp().run()
# Button:
# text: 'Use FallOutTransition'
# on_release: root.manager.transition = FallOutTransition()
# Button:
# text: 'Use RiseInTransition'
# on_release: root.manager.transition = RiseInTransition()