Source code for sailsd.boat
import socket
import math
from functools import wraps
from .sailsd import Sailsd
E_RADIUS = 6378000
[docs]class Boat(object):
'''
A merry sailing boat sailing on the seas.
:param sailsd: an instance of ``sailsd.Sailsd`` to use instead of creating a
new instance
:param auto_update: whether to automatically request updated values on each
attribute request. Setting this to True makes using
``update()`` redundant.
:type auto_update: bool
Some example usage:
>>> boat = sailsd.Boat()
>>> boat.rudder_angle = 0.1
>>> boat.update()
>>> boat.heading
0.758290214606183
>>> boat.speed
4.6089232392605135
>>> boat.latitude, boat.longitude
(0.0009904288095353697, 0.0009966210180718897)
'''
_attrs = (
'latitude',
'longitude',
'heading',
'rudder-angle',
'sail-angle',
'speed',
'sheet-length',
)
def __init__(self, sailsd=None, auto_update=False):
self.sailsd = sailsd or Sailsd()
self.status = 'not connected'
self.auto_update = auto_update
self.values = {}
for a in self._attrs:
self.values.update({a: 0})
self.update()
def _auto_update(f):
@wraps(f)
def dec(self) :
if self.auto_update:
self.update()
return f(self)
return dec
@property
@_auto_update
def x(self):
'''Longitude approximately projected to an x y meter grid'''
return E_RADIUS * (self.longitude / (180 / math.pi))
@property
@_auto_update
def y(self):
'''Latitude approximately projected to an x y meter grid'''
return E_RADIUS * (self.latitude / ((180 / math.pi) /
math.cos(self.latitude * math.pi/180)))
@property
@_auto_update
def latitude(self):
'''Current latitude of the boat'''
return self.values.get('latitude')
@property
@_auto_update
def longitude(self):
'''Current longitude of the boat'''
return self.values.get('longitude')
@property
@_auto_update
def heading(self):
'''Current heading of the boat, measured in radians from the bow'''
return self.values.get('heading')
@property
@_auto_update
def rudder_angle(self):
'''Angle of the rudder, measured in radians where 0 is a straight rudder'''
return self.values.get('rudder-angle')
@rudder_angle.setter
def rudder_angle(self, angle):
self.sailsd.set(rudder_angle=angle)
@property
@_auto_update
def sail_angle(self):
'''Angle of the sail, measured in radians where 0 is the sail pulled to
the exact center of the boat'''
return self.values.get('sail-angle')
@property
@_auto_update
def sheet_length(self):
'''length of the sheet, between 0 and 1'''
return self.values.get('sheet-length')
@sail_angle.setter
def sail_angle(self, angle):
self.sailsd.set(sail_angle=angle)
@sheet_length.setter
def sheet_length(self, length):
self.sailsd.set(sheet_length=length)
@property
@_auto_update
def speed(self):
'''Current speed of the boat, measured in meters per second'''
return self.values.get('speed')
[docs] def update(self):
'''
Read attributes from sailsd and update all values. For example:
>>> boat = sailsd.Boat()
>>> boat.update()
>>> boat.latitude
100.00292426652119
This should be run just before reading values to ensure they are up to
date.
'''
try:
res = self.sailsd.request(*self._attrs)
except socket.error as e:
self.status = 'not connected'
raise
else:
self.status = 'connected'
self.values.update(res)