def testHit(self): self.chart.load(dirname + '/Canary_Brazil.xml') # Attempt to hit Sao Antao (Cabo Verde) from all sides pos_to = Position(0.297869, -0.43921) bearing = Vector(0, 30000) pos_from = pos_to - bearing segment = Line(pos_from, pos_to) hit = self.chart.hit(segment) self.assertTrue(hit) bearing = Vector(1.57, 25000) pos_from = pos_to - bearing segment = Line(pos_from, pos_to) hit = self.chart.hit(segment) self.assertTrue(hit) bearing = Vector(3.14, 25000) pos_from = pos_to - bearing segment = Line(pos_from, pos_to) hit = self.chart.hit(segment) self.assertTrue(hit) bearing = Vector(4.71, 30000) pos_from = pos_to - bearing segment = Line(pos_from, pos_to) hit = self.chart.hit(segment) self.assertTrue(hit) # This point is not on the island pos1 = Position(0.3019, -0.4363) pos2 = pos1 - bearing segment = Line(pos1, pos2) hit = self.chart.hit(segment) self.assertFalse(hit)
class Condition(object): __wind = Vector(0, 0) __current = Vector(0, 0) def __init__(self, *args, **kwargs): super(Condition, self).__init__() if len(args) > 0: wind = args[0] if len(args) > 1: current = args[1] else: current = kwargs['current'] else: wind = kwargs['wind'] self.__wind = Vector(wind[0], wind[1]) self.__current = Vector(current[0], current[1]) @property def wind(self): return self.__wind @wind.setter def wind(self, value): self.__wind = Vector(value[0], value[1]) @property def current(self): return self.__current @current.setter def current(self, value): self.__current = Vector(value[0], value[1])
def veer_vector(vec, right, distance=42): result = Vector(vec) result.r = distance if right: result.a += 0.5 * pi else: result.a -= 0.5 * pi return result
def __init__(self, *args, **kwargs): super(Condition, self).__init__() if len(args) > 0: wind = args[0] if len(args) > 1: current = args[1] else: current = kwargs['current'] else: wind = kwargs['wind'] self.__wind = Vector(wind[0], wind[1]) self.__current = Vector(current[0], current[1])
def active_leg(self): if self.__active_index < len(self.route): return (self.route[self.__active_index] - \ self.route[self.__active_index - 1], self.route[self.__active_index]) else: return Vector(), Waypoint()
def get_bearing(self): if self.is_complete: return Vector(0.0, 0.0) course, waypoint = self.active_leg bearing = waypoint - self.boat.position # If waypoint has been reached or has been 'overshot'... if waypoint.is_reached(self.boat.position) \ or math.cos(course.a - bearing.a) < 0.0: # ... go to the next waypoint self.__next() return self.get_bearing() return bearing
def testOuterPoints(self): self.chart.load(dirname + '/Canary_Brazil.xml') # Attempt to pass Sao Antao (Cabo Verde) from north to south pos_from = Position(0.297869, -0.43921) + Vector(0, 30000) pos_to = Position(0.297869, -0.43921) + Vector(math.pi, 30000) segment = Line(pos_from, pos_to) # First verify that we're hitting hit = self.chart.hit(segment) self.assertTrue(hit, 'Expected island hit') outer_points = self.chart.route_around(segment) self.assertEquals(2, len(outer_points)) self.assertTrue(not outer_points[0] is None \ and not outer_points[1] is None, \ 'Island, so expected two ways to pass (both sides)') # ..now from south to north and the start a little offset to the east # so we'll also hit Sao Vicente pos_from = Position(0.297869, -0.43921) + Vector(math.pi - 0.2, 35000) pos_to = Position(0.297869, -0.43921) + Vector(0, 30000) segment = Line(pos_from, pos_to) # First verify that we're hitting hit = self.chart.hit(segment) self.assertTrue(hit, 'Expected island hit') outer_points = self.chart.route_around(segment) self.assertEquals(2, len(outer_points)) route = Route(outer_points[0]) route.save_to_kml(dirname + '/outer_points_first_0.kml') route = Route(outer_points[1]) route.save_to_kml(dirname + '/outer_points_first_1.kml') outer_points = self.chart.find_paths(segment) for i, points in enumerate(outer_points): path = Path(points) path.save_to_kml('result_%d.kml' % i) # Expected 3 lines around both islands self.assertTrue(len(outer_points) >= 3)
def push_out(points, offset=42, chart=None): if points is None: return None result = [] i = iter(points) try: cur = i.next() result.append(Position(cur)) try: nxt = i.next() v_from = nxt - cur try: while True: prv = cur cur = nxt nxt = i.next() v_to = v_from v_from = nxt - cur ad = angle_diff(v_from.a, v_to.a) o = offset if ad > 0: a = normalize_angle_2pi(v_to.a + 0.5 * (ad - pi)) elif ad < 0: a = normalize_angle_2pi(v_to.a + 0.5 * (ad + pi)) else: a = 0 o = 0 v = Vector(a, o) p = cur + v if chart is not None: l = Line(cur + v * 0.01, p) segment, intersect = chart.intersect(l) if intersect is not None: p = cur + (intersect - cur) * 0.5 result.append(p) except StopIteration: result.append(Position(nxt)) except StopIteration: pass except StopIteration: pass return result
def prevent_beaching(self, heading, look_ahead=None): if look_ahead == None: # 30 seconds of sailing look_ahead = self.boat.motion.speed * 30 # We'll construct a future course line... boat_position = self.boat.position # ... project it ahead... sail_vector = Vector(heading, look_ahead) future_position = boat_position + sail_vector sail_line = Line(self.boat.position, future_position) # Check if the projected line hits land... if self.chart.hit(sail_line): # ... and if so, tack or gybe away from it wind = self.boat.condition.wind wind_angle = normalize_angle_pipi(wind[0] - heading) self.log("Tacked/gybed to avoid hitting land") return True, normalize_angle_2pi(heading + 2 * wind_angle) # Also, we want to keep a clear line of sight to the waypoint track, waypoint = self.navigator.active_leg bearing = waypoint - self.boat.position view_line = Line(self.boat.position, waypoint) if self.chart.hit(view_line): # The only way, we could have gotten something in the view # line is that we were reaching or tacking away from the # track. Tack or gybe now to get back. off_bearing_angle = normalize_angle_pipi(heading - bearing[0]) off_track = self.navigator.get_cross_track() # Check if heading is 'outside' bearing if (off_track > 0) == (off_bearing_angle > 0): # ...or tack/gybe when they don't wind = self.boat.condition.wind wind_angle = normalize_angle_pipi(wind[0] - heading) self.log("Tacked/gybed to avoid land getting in line of sight") return True, normalize_angle_2pi(heading + 2 * wind_angle) # Nothing needed to be done. Return the originally suggested heading return False, heading
def velocity(self): return Vector(self.course, self.speed)
def __init__(self, *args, **kwargs): super(Course, self).__init__() chart = None if len(args) > 0: waypoints = args[0] if len(args) > 1: finish_radius = args[1] if len(args) > 2: chart = args[2] try: waypoints = kwargs['waypoints'] except KeyError: pass try: finish_radius = kwargs['finish_radius'] except KeyError: pass try: chart = kwargs['map'] except KeyError: pass try: chart = kwargs['chart'] except KeyError: pass self._chart = chart self._start = Position(waypoints[0][0], waypoints[0][1]) self._finish = Finish(waypoints[-1][0], waypoints[-1][1]) # Enrich waypoints to turn them into marks for i in range(1, len(waypoints) - 1): prev = Position(waypoints[i - 1][0], waypoints[i - 1][1]) mark = Mark(waypoints[i][0], waypoints[i][1]) nxt = Position(waypoints[i + 1][0], waypoints[i + 1][1]) v1 = mark - prev v2 = nxt - mark a1 = angle_diff(v2.a, v1.a) mark.to_port = a1 < 0 mark.on_land = self.get_on_land(mark) if mark.to_port: a2 = normalize_angle_2pi(v1.a + 0.5 * (a1 + pi)) else: a2 = normalize_angle_2pi(v1.a + 0.5 * (a1 - pi)) mark.target_vector = Vector(a2, 1) if mark.on_land: intersection = None dist = 0 for j in range(-49, 50): a = a2 + j * (0.01 + 0.003 * math.fabs(a1)) perp = Line(mark, mark + Vector(a, 42000)) chart_segment, intersect = self._chart.intersect(perp) # We may not find an intersection for all angles if intersect is not None: v = intersect - mark if v.r > dist: dist = v.r intersection = intersect if intersection is None: raise Exception( 'No waterfront found for Mark %d. Mark far inland?' % i) mark.set_target(intersection + mark.target_vector * 42) else: mark.set_target(mark + mark.target_vector * 42) self._marks.append(mark) # Construct finish line finish_leg = self._finish - Position(waypoints[-2][0], waypoints[-2][1]) self._finish.left = self._finish + Vector(finish_leg.a - half_pi, finish_radius) self._finish.right = self._finish + Vector(finish_leg.a + half_pi, finish_radius)
class Mark(Mark): target_vector = Vector()
def get_current(self, lat, lon, time=None): return Vector(0, 0)
def get_wind(self, lat, lon, time=None): return Vector(0, 0)
def current(self, value): self.__current = Vector(value[0], value[1])
def wind(self, value): self.__wind = Vector(value[0], value[1])