예제 #1
0
    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)
예제 #2
0
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])
예제 #3
0
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
예제 #4
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])
예제 #5
0
 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()
예제 #6
0
 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
예제 #7
0
    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)
예제 #8
0
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
예제 #9
0
    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
예제 #10
0
 def velocity(self):
     return Vector(self.course, self.speed)
예제 #11
0
    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)
예제 #12
0
class Mark(Mark):
    target_vector = Vector()
예제 #13
0
 def get_current(self, lat, lon, time=None):
     return Vector(0, 0)
예제 #14
0
 def get_wind(self, lat, lon, time=None):
     return Vector(0, 0)
예제 #15
0
 def current(self, value):
     self.__current = Vector(value[0], value[1])
예제 #16
0
 def wind(self, value):
     self.__wind = Vector(value[0], value[1])