2020-07-17 02:12:36 +00:00
|
|
|
from plyer import gps
|
2020-07-16 16:25:49 +00:00
|
|
|
from kivy.app import App
|
2020-07-16 22:42:33 +00:00
|
|
|
from kivy.clock import Clock
|
2020-07-16 18:43:28 +00:00
|
|
|
from kivy.properties import NumericProperty, StringProperty
|
|
|
|
|
from kivy.clock import mainthread
|
|
|
|
|
from kivy.utils import platform
|
2020-07-17 02:12:36 +00:00
|
|
|
|
|
|
|
|
from kivy.uix.screenmanager import ScreenManager, Screen, RiseInTransition
|
|
|
|
|
|
|
|
|
|
from kivy_garden.mapview import MapView
|
|
|
|
|
|
2020-07-17 00:17:49 +00:00
|
|
|
from kivy.vector import Vector
|
|
|
|
|
from kivy.animation import Animation
|
|
|
|
|
from math import floor
|
2020-08-04 22:20:08 +00:00
|
|
|
import random
|
2020-07-16 18:43:28 +00:00
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
from pprint import pprint
|
2020-07-16 16:25:49 +00:00
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
root = None
|
2020-07-16 16:25:49 +00:00
|
|
|
|
2020-08-04 22:20:08 +00:00
|
|
|
class MapScreen(Screen):
|
2020-08-05 02:52:20 +00:00
|
|
|
|
|
|
|
|
def choose_destination(self):
|
|
|
|
|
root.parent.dest_lat = self.ids.centermark.lat
|
|
|
|
|
root.parent.dest_lon = self.ids.centermark.lon
|
|
|
|
|
|
2020-07-17 00:17:49 +00:00
|
|
|
|
2020-07-16 16:25:49 +00:00
|
|
|
class CompassScreen(Screen):
|
2020-07-16 22:42:33 +00:00
|
|
|
x_calib = NumericProperty(0)
|
|
|
|
|
y_calib = NumericProperty(0)
|
|
|
|
|
z_calib = NumericProperty(0)
|
2020-07-17 00:17:49 +00:00
|
|
|
|
2020-07-17 02:12:36 +00:00
|
|
|
needle_angle = NumericProperty(0)
|
|
|
|
|
gps_location = StringProperty()
|
|
|
|
|
gps_status = StringProperty('Click Start to get GPS location updates')
|
2020-07-17 00:17:49 +00:00
|
|
|
|
2020-07-16 22:42:33 +00:00
|
|
|
|
|
|
|
|
def get_field(self, dt):
|
2020-07-17 00:17:49 +00:00
|
|
|
needle_angle = 7
|
2020-07-16 22:42:33 +00:00
|
|
|
if self.facade.field != (None, None, None):
|
|
|
|
|
self.x_calib, self.y_calib, self.z_calib = self.facade.field
|
2020-07-17 00:17:49 +00:00
|
|
|
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.)
|
2020-07-16 16:25:49 +00:00
|
|
|
|
2020-07-17 00:17:49 +00:00
|
|
|
# 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)
|
|
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
def sensors_start(self):
|
|
|
|
|
self.compass_enable()
|
|
|
|
|
self.gps_start(1000, 0)
|
|
|
|
|
|
|
|
|
|
def sensors_stop(self):
|
|
|
|
|
self.compass_disable()
|
|
|
|
|
self.gps_stop()
|
2020-07-17 00:17:49 +00:00
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
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):
|
2020-07-17 00:17:49 +00:00
|
|
|
gps.start(minTime, minDistance)
|
|
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
def gps_stop(self):
|
2020-07-17 00:17:49 +00:00
|
|
|
gps.stop()
|
|
|
|
|
|
|
|
|
|
def on_pause(self):
|
2020-08-05 02:52:20 +00:00
|
|
|
self.compass_disable()
|
|
|
|
|
self.gps_stop()
|
2020-07-17 00:17:49 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def on_resume(self):
|
2020-08-05 02:52:20 +00:00
|
|
|
self.compass_enable()
|
|
|
|
|
self.gps_start(1000, 0)
|
2020-07-17 00:17:49 +00:00
|
|
|
|
2020-07-16 18:43:28 +00:00
|
|
|
@mainthread
|
|
|
|
|
def on_location(self, **kwargs):
|
2020-08-05 02:52:20 +00:00
|
|
|
|
|
|
|
|
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))
|
2020-08-04 22:20:08 +00:00
|
|
|
# bearing = degrees(bearing)
|
|
|
|
|
# bearing = (bearing + 360) % 360
|
|
|
|
|
# https://stackoverflow.com/questions/4913349/haversine-formula-in-python-bearing-and-distance-between-two-gps-points#4913653
|
2020-08-05 02:52:20 +00:00
|
|
|
|
|
|
|
|
|
2020-07-16 18:43:28 +00:00
|
|
|
@mainthread
|
|
|
|
|
def on_status(self, stype, status):
|
|
|
|
|
self.gps_status = 'type={}\n{}'.format(stype, status)
|
2020-07-17 00:17:49 +00:00
|
|
|
|
|
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
|
2020-07-17 02:12:36 +00:00
|
|
|
|
|
|
|
|
class FlockompassApp(App):
|
|
|
|
|
|
2020-08-04 22:20:08 +00:00
|
|
|
lat = 19.3419
|
|
|
|
|
lon = -99.1499
|
|
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
dest_lat = 19.3429
|
|
|
|
|
dest_lon = -99.15
|
|
|
|
|
|
2020-08-04 22:20:08 +00:00
|
|
|
def move_around(self, t):
|
|
|
|
|
self.lat += random.uniform(-0.01,0.01)
|
2020-08-05 02:52:20 +00:00
|
|
|
self.lon += random.uniform(-0.01,0.01)
|
2020-08-04 22:20:08 +00:00
|
|
|
|
|
|
|
|
self.ms.ids.mapview.center_on(self.lat, self.lon)
|
|
|
|
|
|
|
|
|
|
# where the marker's at
|
|
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
|
2020-07-17 02:12:36 +00:00
|
|
|
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)
|
|
|
|
|
|
2020-07-16 16:25:49 +00:00
|
|
|
def build(self):
|
2020-08-05 02:52:20 +00:00
|
|
|
global root
|
2020-07-16 18:43:28 +00:00
|
|
|
|
2020-07-17 02:12:36 +00:00
|
|
|
root = ScreenManager(transition=RiseInTransition())
|
2020-08-05 02:52:20 +00:00
|
|
|
|
2020-08-04 22:20:08 +00:00
|
|
|
self.ms = MapScreen(name='map')
|
|
|
|
|
root.add_widget(self.ms)
|
|
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
|
2020-07-17 02:12:36 +00:00
|
|
|
cs = CompassScreen(name='compass')
|
|
|
|
|
cs._anim = None
|
2020-08-04 22:20:08 +00:00
|
|
|
cs.p = None
|
2020-08-05 02:52:20 +00:00
|
|
|
root.add_widget(cs)
|
|
|
|
|
|
2020-07-16 18:43:28 +00:00
|
|
|
|
|
|
|
|
if platform == "android":
|
|
|
|
|
print("gps.py: Android detected. Requesting permissions")
|
|
|
|
|
self.request_android_permissions()
|
2020-07-17 00:17:49 +00:00
|
|
|
|
2020-08-04 22:20:08 +00:00
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
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')
|
2020-07-17 00:17:49 +00:00
|
|
|
|
2020-08-05 02:52:20 +00:00
|
|
|
Clock.schedule_interval(self.move_around, 7.0)
|
2020-08-04 22:20:08 +00:00
|
|
|
|
2020-07-16 16:25:49 +00:00
|
|
|
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()
|