Exemple #1
0
    def on_run(self, *args):
        if self.last_run_time is None:
            return

        dt = self.this_run_time - self.last_run_time

        self.revolve_angle += self.degrees_per_second * dt

        if self.revolve_angle > 390:
            Heading(self.initial_heading)()
            Pitch(0)()
            Roll(0)()
            self.finish()
            return

        rot_2d = rotate((0, 1), self.revolve_angle)
        rotation_axis = np.array((rot_2d[0], rot_2d[1], 0))

        conic_quat = quat_from_axis_angle(rotation_axis, self.conic_angle_rad)
        pointing_vector = conic_quat * np.array((0, 0, 1))

        # TODO How can we achieve the same effect without using heading?
        heading, pitch, roll = conic_quat.hpr()

        Heading(heading)()
        Pitch(pitch)()
        Roll(roll)()
Exemple #2
0
    def on_run(self, *args):
        if self.last_run_time is None:
            return

        dt = self.this_run_time - self.last_run_time

        self.revolve_angle += self.degrees_per_second * dt

        if self.revolve_angle > 390:
            Heading(self.initial_heading)()
            Pitch(0)()
            Roll(0)()
            self.finish()
            return

        rot_2d = rotate((0, 1), self.revolve_angle)
        rotation_axis = np.array((rot_2d[0], rot_2d[1], 0))

        conic_quat = quat_from_axis_angle(rotation_axis, self.conic_angle_rad)

        # TODO How can we achieve the same effect without using heading?
        heading, pitch, roll = conic_quat.hpr()

        Heading(heading)()
        Pitch(pitch)()
        Roll(roll)()
Exemple #3
0
    def on_first_run(self, vector, deadband=0.01, *args, **kwargs):
        self.pos_con_man = PositionalControlManager()
        self.pos_con_man.set(1)

        delta_north, delta_east = rotate(vector, kalman.heading.get())

        n_position = RelativeToInitialPositionN(offset=delta_north, error=deadband)
        e_position = RelativeToInitialPositionE(offset=delta_east, error=deadband)
        self.motion = Concurrent(n_position, e_position, finite=False)
Exemple #4
0
    def on_first_run(self, vector, deadband=0.01, *args, **kwargs):
        delta_north, delta_east = rotate(vector, kalman.heading.get())

        n_position = RelativeToInitialPositionN(offset=delta_north,
                                                error=deadband)
        e_position = RelativeToInitialPositionE(offset=delta_east,
                                                error=deadband)
        self.use_task(
            WithPositionalControl(
                Concurrent(n_position, e_position, finite=False), ))
Exemple #5
0
 def on_first_run(self):
   self.heading        = shm.kalman.heading.get()
   self.red_buoy       = aslam.world.red_buoy.position()[:2]
   self.green_buoy     = aslam.world.green_buoy.position()[:2]
   self.yellow_buoy    = aslam.world.yellow_buoy.position()[:2]
   self.all_buoys      = [('red', self.red_buoy), ('green', self.green_buoy), ('yellow', self.yellow_buoy)]
   self.sorted_buoys   = sorted(self.all_buoys, key = lambda x: rotate(x[1], -self.heading)[1])
   self.logi('Sorted buoys (left-to-right): {}'.format([x[0] for x in self.sorted_buoys]))
   subtasks = []
   subtasks.append(MasterConcurrent(HPRWiggle(), MoveXRough(-1.0)))
   subtasks.append(Depth(PIPE_SEARCH_DEPTH))
   if self.sorted_buoys[0][0] == 'yellow':
       # yellow buoy far left, go right
       subtasks.append(MoveYRough(1.0))
   elif self.sorted_buoys[1][0] == 'yellow':
       subtasks.append(MoveYRough(1.0))
   else:
       subtasks.append(MoveYRough(-1.0))
   subtasks.append(MoveXRough(1.0))
   center_buoy = n.array(self.sorted_buoys[1][1])
   center_buoy += n.array(rotate((1, 0), self.heading)) # 1m beyond center buoy
   subtasks.append(GoToPosition(center_buoy[0], center_buoy[1], depth=PIPE_SEARCH_DEPTH))
   self.subtask = Sequential(*subtasks)
Exemple #6
0
 def on_first_run(self):
   self.heading        = shm.kalman.heading.get()
   self.red_buoy       = aslam.world.red_buoy.position()[:2]
   self.green_buoy     = aslam.world.green_buoy.position()[:2]
   self.yellow_buoy    = aslam.world.yellow_buoy.position()[:2]
   self.all_buoys      = [('red', self.red_buoy), ('green', self.green_buoy), ('yellow', self.yellow_buoy)]
   self.sorted_buoys   = sorted(self.all_buoys, key = lambda x: rotate(x[1], -self.heading)[1])
   self.logi('Sorted buoys (left-to-right): {}'.format([x[0] for x in self.sorted_buoys]))
   subtasks = []
   subtasks.append(MasterConcurrent(HPRWiggle(), MoveXRough(-1.0)))
   subtasks.append(Depth(PIPE_SEARCH_DEPTH))
   if self.sorted_buoys[0][0] == 'yellow':
       # yellow buoy far left, go right
       subtasks.append(MoveYRough(1.0))
   elif self.sorted_buoys[1][0] == 'yellow':
       subtasks.append(MoveYRough(1.0))
   else:
       subtasks.append(MoveYRough(-1.0))
   subtasks.append(MoveXRough(1.0))
   center_buoy = n.array(self.sorted_buoys[1][1])
   center_buoy += n.array(rotate((1, 0), self.heading)) # 1m beyond center buoy
   subtasks.append(GoToPosition(center_buoy[0], center_buoy[1], depth=PIPE_SEARCH_DEPTH))
   self.subtask = Sequential(*subtasks)
    def follow_heading(self, new_ping):
        distance_to_pinger = self.elevation_to_distance(new_ping.elevation)
        speed = self.get_follow_speed(distance_to_pinger)

        # Check if the ping suggests the pinger is in a heading deviating from
        # the current follow heading
        new_ping_heading = (new_ping.heading + shm.kalman.heading.get()) % 360
        heading_deviation = abs(new_ping_heading - self.heading_to_pinger)

        # When we are close to the pinger, headings will vary more, allow for
        # deviation

        # Note, this is fairly broken, because it assumes we get good pings
        # while moving! Realistically, we should just move forward for a set time,
        # and then get new heading. BUT, since the consistency check will really
        # just wait for the requisite number of pings (since its a safe assumption
        # that we're just getting garbage), we can essentially turn this into
        # a makeshift timer by changing the window size on consistency check (:139)
        if new_ping.elevation > MIN_DEVIATING_PING_ELEVATION:
            deviating_ping = heading_deviation > MAX_FOLLOW_HEADING_DEVIATION

            if deviating_ping:
                self.logi(
                    "Ping heading deviated from follow heading by %0.3f, more "
                    "than maximum allowed" % heading_deviation)
            else:
                self.heading_to_pinger = new_ping_heading

            if self.ping_deviating_checker.check(deviating_ping):
                self.logi(
                    "Consistently getting deviating pings! Stopping to listen."
                )
                self.ping_deviating_checker.clear()

                return "listen"

            self.logi("Going straight for the pinger!")
            self.follow_vel_x(x_dir * speed)
            self.follow_vel_y(0.0)
            self.follow_change_heading(self.heading_to_pinger + heading_offset)
        else:
            velocity = rotate([speed, 0], new_ping.heading)
            self.logi("We are close! Translating to pinger: Velocity (%0.3f, "
                      "%0.3f)" % (velocity[0], velocity[1]))
            self.follow_vel_x(velocity[0])
            self.follow_vel_y(velocity[1])

        return None
Exemple #8
0
    def follow_heading(self, new_ping):
        distance_to_pinger = self.elevation_to_distance(new_ping.elevation)
        speed = self.get_follow_speed(distance_to_pinger)

        # Check if the ping suggests the pinger is in a heading deviating from
        # the current follow heading
        new_ping_heading = (new_ping.heading + shm.kalman.heading.get()) % 360
        heading_deviation = abs(new_ping_heading - self.heading_to_pinger)

        # When we are close to the pinger, headings will vary more, allow for
        # deviation
        if new_ping.elevation > MIN_DEVIATING_PING_ELEVATION:
            deviating_ping = heading_deviation > MAX_FOLLOW_HEADING_DEVIATION

            if deviating_ping:
                self.logi(
                    "Ping heading deviated from follow heading by %0.3f, more "
                    "than maximum allowed" % heading_deviation)
            else:
                self.heading_to_pinger = new_ping_heading

            if self.ping_deviating_checker.check(deviating_ping):
                self.logi(
                    "Consistently getting deviating pings! Stopping to listen."
                )
                self.ping_deviating_checker.clear()

                return "listen"

            self.logi("Going straight for the pinger!")
            self.follow_vel_x(speed)
            self.follow_vel_y(0.0)
            self.follow_change_heading(self.heading_to_pinger)
        else:
            velocity = rotate([speed, 0], new_ping.heading)
            self.logi("We are close! Translating to pinger: Velocity (%0.3f, "
                      "%0.3f)" % (velocity[0], velocity[1]))
            self.follow_vel_x(velocity[0])
            self.follow_vel_y(velocity[1])

        return None
Exemple #9
0
 def on_first_run(self, angle, distance, deadband=0.01, *args, **kwargs):
     super().on_first_run(rotate((distance, 0), angle), deadband=deadband)
Exemple #10
0
 def on_first_run(self, angle, distance, deadband=0.01, *args, **kwargs):
     super().on_first_run(rotate((distance, 0), angle), deadband=deadband)
Exemple #11
0
  def on_run(self):
    self.motion_tasks()

    self.silencer()

    # TODO Better way to filter out bad pings when thrusters are running.
    if not self.hydro_watcher.has_changed() or \
       (not LISTEN_WHILE_MOVING and not self.motion_tasks.finished):
      # TODO Do something here if too much time has passed since last ping.
      return

    if self.pinger_found:
      self.finish()
      return

    self.time_since_last_ping = self.this_run_time
    self.pings_here += 1

    # TODO Will this be long after the watcher fired?
    # Need to ensure that there is little delay.
    results = shm.hydrophones_results_track.get()
    kalman = shm.kalman.get()

    phases = (results.diff_phase_x, results.diff_phase_y)
    self.logi("Got " + str(phases))

    in_silence = self.silencer.in_silence()

    # TODO Better way to detect ping period.
    self.silencer.schedule_silence(self.this_run_time + PINGER_PERIOD - 0.1, 0.4)

    if not in_silence:
      return

    sub_pos = get_sub_position(kalman)
    sub_quat = get_sub_quaternion(kalman)
    ping_data = PingData(phases, sub_pos, sub_quat)
    self.pings.append(ping_data)

    if len(self.pings) < 2:
      return

    if not CLUSTER_HEADINGS:
      data = get_clusterable([ping.phases[0] for ping in self.pings])
      clusters = fclusterdata(data, 0.3, criterion="distance")
    else:
      headings, elevations = zip(*[self.localizer.get_heading_elevation(*ping.phases) for ping in self.pings])
      data = get_clusterable(headings)
      clusters = fclusterdata(data, 8, criterion="distance")

    counted = collections.Counter(clusters)

    best_cluster, n_best = max(counted.items(), key=lambda item: item[1])
    if n_best >= self.CONSISTENT_PINGS:
      good_pings = [self.pings[i] for i, cluster_num in enumerate(clusters) \
                    if cluster_num == best_cluster]
      avg_phase_x = np.mean([ping.phases[0] for ping in good_pings])
      avg_phase_y = np.mean([ping.phases[1] for ping in good_pings])

      self.logi("Found nice phases (%f, %f) in %s" % \
                (avg_phase_x, avg_phase_y, str(self.pings)))

      for ping in good_pings:
        self.localizer.add_observation(ping.phases, ping.sub_pos, ping.sub_quat)

      est_pinger_pos = self.localizer.compute_position()[USE_THREE]
      self.pinger_positions.append(est_pinger_pos)

      self.logi("We think the pinger is at %s" % str(est_pinger_pos))
      self.logi("All estimated positions: %s" % str(self.pinger_positions))

      if len(self.pinger_positions) > 5:
        data = np.array(self.pinger_positions)
        clusters = fclusterdata(data, 0.6, criterion="distance")
        counted = collections.Counter(clusters)
        best_cluster, n_best = max(counted.items(), key=lambda item: item[1])
        if n_best >= 3:
          avg_position = sum([np.array(self.pinger_positions[i]) for i, cluster_num in enumerate(clusters) if cluster_num == best_cluster]) / n_best
          self.logi("Found pinger at %0.2f %0.2f using localization!" % \
                    (avg_position[0], avg_position[1]))
          self.observe_from(avg_position)
          self.pinger_found = True
          return

      if FOLLOW_HEADING:
        heading, elevation = self.localizer.get_heading_elevation(avg_phase_x, avg_phase_y)

        depth_distance = HYDROPHONES_PINGER_DEPTH - kalman.depth
        distance = math.tan(math.radians(elevation)) * depth_distance

        # Elevations seem to be wrong; nerf them.
        distance = min(0.5 * distance, 4.2)

        direction = rotate((1, 0), kalman.heading + heading)
        observe_position = sub_pos + np.array((direction[0], direction[1], sub_pos[2])) * distance
        self.logi("Heading is %f, Elevation is %f" % (heading, elevation))
        self.observe_from(observe_position, kalman.heading + heading)

        if self.elevation_checker(elevation < 25):
          self.logi("Found pinger using elevations!")
          self.pinger_found = True

      elif not FOLLOW_HEADING:
        if self.listens <= 3:
          # TODO Change heading in an optimal fashion.
          self.observe_from(sub_pos, heading=(kalman.heading + 30) % 360)
        else:
          if not self.queued_moves:
            to_pinger = est_pinger_pos[:2] - sub_pos[:2]
            distance = np.linalg.norm(to_pinger)
            direction = to_pinger / distance

            move_dist = 3
            if self.listens > 10 and distance < 3:
              move_dist = distance

            new_pos = sub_pos[:2] + direction * move_dist
            heading = math.atan2(direction[1], direction[0])

            if DO_PARALLAX:
              perp = np.array(rotate(direction, 90))
              self.queued_moves.extend([(new_pos, heading), (new_pos + 2 * perp, heading), (new_pos - 2 * perp, heading)])

            else:
              if PERP_TO_PINGER:
                heading += 90
              self.queued_moves.extend([(new_pos, heading+30), (new_pos, heading-30), (new_pos, heading)])

          next_pos, heading = self.queued_moves.pop(0)
          self.observe_from(next_pos, heading)
Exemple #12
0
  def on_run(self):
    self.motion_tasks()

    self.silencer()

    # TODO Better way to filter out bad pings when thrusters are running.
    if not self.hydro_watcher.has_changed() or \
       not self.motion_tasks.finished:
      # TODO Do something here if too much time has passed since last ping.
      return

    if self.pinger_found:
      self.finish()
      return

    self.time_since_last_ping = self.this_run_time
    self.pings_here += 1

    # TODO Will this be long after the watcher fired?
    # Need to ensure that there is little delay.
    results = shm.hydrophones_results_track.get()
    kalman = shm.kalman.get()

    phases = (results.diff_phase_x, results.diff_phase_y)
    self.logi("Got " + str(phases))

    in_silence = self.silencer.in_silence()

    self.silencer.schedule_silence(self.this_run_time + 0.9, 0.4)

    if not in_silence:
      return

    self.pings.append(results.diff_phase_x)

    if len(self.pings) < 2:
      return

    data = get_clusterable(self.pings)
    clusters = fclusterdata(data, 0.1, criterion="distance")
    counted = collections.Counter(clusters)

    best_cluster, n_best = max(counted.items(), key=lambda item: item[1])
    if n_best >= self.CONSISTENT_PINGS:
      avg_phase = sum([self.pings[i] for i, cluster_num in enumerate(clusters) if cluster_num == best_cluster]) / n_best

      self.logi("Found nice phase %f in %s" % (avg_phase, str(self.pings)))

      if FOLLOW_HEADING:
        # TODO Use average x and y phases here.
        heading, elevation = self.localizer.get_heading_elevation(*phases)

        if elevation > 45:
          move_distance = 4
        elif elevation > 30:
          move_distance = 2
        else:
          move_distance = 1

        sub_pos = get_sub_position(kalman)
        direction = rotate((1, 0), kalman.heading + heading)
        observe_position = sub_pos + np.array((direction[0], direction[1], sub_pos[2])) * move_distance
        self.logi("Heading is %f, Elevation is %f" % (heading, elevation))
        self.observe_from(observe_position, kalman.heading + heading)

      elif not FOLLOW_HEADING:
        sub_pos = get_sub_position(kalman)
        sub_quat = get_sub_quaternion(kalman)

        self.localizer.add_observation(phases, sub_pos, sub_quat)

        # For now, use the estimate from only 2 transducers.
        est_pinger_pos = self.localizer.compute_position()[USE_THREE]
        self.pinger_positions.append(est_pinger_pos)

        self.logi("We think the pinger is at %s" % str(est_pinger_pos))
        self.logi("All estimated positions: %s" % str(self.pinger_positions))

        if len(self.pinger_positions) > 5:
          data = np.array(self.pinger_positions)
          clusters = fclusterdata(data, 0.5, criterion="distance")
          counted = collections.Counter(clusters)
          best_cluster, n_best = max(counted.items(), key=lambda item: item[1])
          if n_best > 3:
            avg_position = sum([np.array(self.pinger_positions[i]) for i, cluster_num in enumerate(clusters) if cluster_num == best_cluster]) / n_best
            self.logi("Found pinger at %0.2f %0.2f!" % (avg_position[0], avg_position[1]))
            self.observe_from(avg_position)
            self.pinger_found = True
            return

        if self.listens <= 3:
          # TODO Change heading in an optimal fashion.
          self.observe_from(sub_pos, heading=(kalman.heading + 30) % 360)
        else:
          if not self.queued_moves:
            to_pinger = est_pinger_pos[:2] - sub_pos[:2]
            distance = np.linalg.norm(to_pinger)
            direction = to_pinger / distance

            move_dist = 3
            if self.listens > 10 and distance < 3:
              move_dist = distance

            new_pos = sub_pos[:2] + direction * move_dist
            heading = math.atan2(direction[1], direction[0])

            if DO_PARALLAX:
              perp = np.array(rotate(direction, 90))
              self.queued_moves.extend([(new_pos, heading), (new_pos + 2 * perp, heading), (new_pos - 2 * perp, heading)])

            else:
              if PERP_TO_PINGER:
                heading += 90
              self.queued_moves.extend([(new_pos, heading+30), (new_pos, heading-30), (new_pos, heading)])

          next_pos, heading = self.queued_moves.pop(0)
          self.observe_from(next_pos, heading)
Exemple #13
0
 def calculate_bin_vector(bin1, bin2):
   body_frame = [(bin1.x, bin1.y), (bin2.x, bin2.y)]
   world_frame = [np.array(rotate(body, -shm.kalman.heading.get())) for body in body_frame]
   bin2bin = world_frame[1] - world_frame[0]
   return bin2bin / np.linalg.norm(bin2bin)