Exemple #1
0
class LidarTest(Robot):
    def __init__(self, enable_plotting=True):
        self.turret = LidarTurret()
        self.slam = SLAM(self.turret)

        super(LidarTest, self).__init__(self.turret)

        self.plotter = LivePlotter(
            1, self.turret.point_cloud_plot, enabled=enable_plotting
        )
        self.slam_plots = SlamPlots(self.slam.map_size_pixels, self.slam.map_size_meters, skip_count=0)
        self.lidar_t0 = 0.0

        self.link_object(self.turret, self.received_lidar)

    def received_lidar(self, timestamp, packet, packet_type):
        if self.turret.did_cloud_update():
            if self.turret.is_cloud_ready():
                self.slam.update(timestamp, self.turret.distances, [0, 0, self.dt() - self.lidar_t0])
                self.slam_plots.update(self.slam.mapbytes, self.slam.get_pos())

                self.lidar_t0 = self.dt()
            return self.plotter.plot()

    def close(self, reason):
        if reason == "done":
            self.plotter.freeze_plot()
        self.plotter.close()
        self.slam.make_image(self.logger.full_path + " post map")
Exemple #2
0
class TutRunner(RobotInterface):
    def __init__(self):
        self.tut = GPS()
        self.time_plot = RobotPlot("gps time")
        self.minute_plot = RobotPlot("gps minutes")
        self.plotter = LivePlotter(2, self.time_plot, self.minute_plot)

        super(TutRunner, self).__init__(
            self.tut,
            debug_prints=True,
            log_data=False,
        )

    def loop(self):
        pass

    def packet_received(self, timestamp, whoiam, packet):
        if self.did_receive(self.tut):
            if self.queue_len() < 25:
                self.time_plot.append(timestamp, self.tut.second)
                self.minute_plot.append(timestamp, self.tut.minute)
                if not self.plotter.plot():
                    return False

    def close(self):
        self.plotter.close()

    def start(self):
        self.plotter.start_time(self.start_time)
class RoboQuasar(Interface):
    def __init__(self, set_num=-1):
        self.gps = GPS()
        self.imu = IMU()
        self.turret = LidarTurret()

        self.steering = Steering()
        self.brakes = Brakes()
        self.underglow = Underglow()

        joystick = None

        if only_lidar:
            self.gps.enabled = False
            self.imu.enabled = False
            self.steering.enabled = False
            self.brakes.enabled = False
            self.underglow.enabled = False
        elif not simulated:
            joystick = WiiUJoystick()

        if args.includelidar:
            self.turret.enabled = False

        # self.imu_plot = RobotPlot("Magnetometer data (x, z vs. time)", flat_plot=True, skip_count=20,
        #                           plot_enabled=False)
        self.kalman_plots = KalmanPlots(not only_lidar, use_filter, animate)

        if animate:
            if args.includelidar:
                self.turret.point_cloud_plot.enabled = False
            self.live_plot = LivePlotter(2,
                                         self.kalman_plots.filter_comparison,
                                         self.turret.point_cloud_plot,
                                         skip_count=10)

            if self.turret.point_cloud_plot.enabled:
                self.live_plot.draw_dot(self.turret.point_cloud_plot,
                                        0,
                                        0,
                                        color='orange',
                                        markersize=5)
        elif plots_enabled:
            self.static_plot = StaticPlotter(
                1, self.kalman_plots.filter_comparison)

        self.filter = None

        # m = np.array(MapFile("buggy course checkpoints").map)
        # self.map_plot.update(m[:, 0], m[:, 1])

        file_sets = (
            ("16;49", "2017_Feb_17"),  # default, latest

            # data day 4
            # ("15", "data_days/2017_Feb_14"),  # filter explodes, LIDAR interfered by the sun
            # ("16;20", "data_days/2017_Feb_14"),  # shorten run, LIDAR collapsed
            # ("16;57", "data_days/2017_Feb_14"),  # interfered LIDAR
            # ("17;10", "data_days/2017_Feb_14"),  # all data is fine, interfered LIDAR
            # ("17;33", "data_days/2017_Feb_14"),  # data is fine, normal run

            # data day 3
            # ("16;38", "data_days/2017_Feb_08"),
            # ("17", "data_days/2017_Feb_08"),
            # ("18", "data_days/2017_Feb_08"),

            # trackfield no gyro values
            # ("15;46", "old_data/2016_Dec_02"),
            # ("15;54", "old_data/2016_Dec_02"),
            # ("16;10", "old_data/2016_Dec_02"),
            # ("16;10", "old_data/2016_Dec_02")

            # rolls day 1
            # ("07;22", "old_data/2016_Nov_06"),  # bad gyro values

            # rolls day 2
            # ("07;36;03 m", "old_data/2016_Nov_12"),
            # ("09;12", "old_data/2016_Nov_12"),  # invalid values
            # ("07;04;57", "old_data/2016_Nov_13"),  # bad gyro values

            # rolls day 3
            # ("modified 07;04", "old_data/2016_Nov_13"),
            # ("modified 07;23", "old_data/2016_Nov_13"),  # wonky value for mag.

            # rolling on the cut
            # ("16;29", "old_data/2016_Dec_09"),
            # ("16;49", "old_data/2016_Dec_09"),
            # ("16;5", "old_data/2016_Dec_09"),
            # ("17;", "old_data/2016_Dec_09"),  # nothing wrong, really short

            # bad data
            # ("16;07", "old_data/2016_Dec_09/bad_data"),  # nothing wrong, really short
            # ("16;09", "old_data/2016_Dec_09/bad_data"),  # nothing wrong, really short
            # ("18;00", "old_data/2016_Dec_09/bad_data"),  # gps spazzed out
            # ("18;02", "old_data/2016_Dec_09/bad_data"),  # gps spazzed out
            # ("18;09", "old_data/2016_Dec_09/bad_data"),  # gps spazzed out
        )

        self.checkpoint_num = 0

        self.lat1, self.long1, self.alt1 = 0, 0, 0
        self.lat2, self.long2, self.alt2 = 0, 0, 0
        self.num_recv_from_fix = None
        self.received_fix = False

        self.imu_t0 = 0
        self.gps_t0 = 0
        self.lidar_t0 = 0

        if simulated:
            super(RoboQuasar, self).__init__(
                file_sets[set_num][0],
                file_sets[set_num][1],
                self.gps,
                self.imu,
                self.turret,
                start_index=10000,
                # end_index=2000,
            )

            extension_index = self.parser.full_path.rfind(".")
            image_path = self.parser.full_path[:extension_index]
        else:
            super(RoboQuasar, self).__init__(self.imu,
                                             self.gps,
                                             self.steering,
                                             self.brakes,
                                             self.underglow,
                                             self.turret,
                                             joystick=joystick,
                                             debug_prints=args.verbose,
                                             log_data=args.log)

            extension_index = self.logger.full_path.rfind(".")
            image_path = self.logger.full_path[:extension_index]

        self.slam = SLAM(self.turret, image_path + " post map")
        self.slam_plots = SlamPlots(self.slam.map_size_pixels,
                                    self.slam.map_size_meters,
                                    args.computeslam)

    def init_filter(self, timestamp):
        self.lat2, self.long2, self.alt2 = self.gps.latitude_deg, self.gps.longitude_deg, self.gps.altitude
        roll, pitch, yaw = get_gps_orientation(self.lat1, self.long1,
                                               self.alt1, self.lat2,
                                               self.long2, self.alt2)

        yaw = math.atan2(self.lat2 - self.lat1, self.long2 - self.long1)
        print(math.degrees(roll), math.degrees(pitch), math.degrees(yaw))

        self.filter = GrovesKalmanFilter(initial_roll=roll,
                                         initial_pitch=pitch,
                                         initial_yaw=yaw,
                                         initial_lat=self.lat2,
                                         initial_long=self.long2,
                                         initial_alt=self.alt2,
                                         **constants)

        self.imu_t0 = timestamp
        self.gps_t0 = timestamp
        self.lidar_t0 = timestamp

        self.kalman_plots.update_gps(self.gps.latitude_deg,
                                     self.gps.longitude_deg, self.gps.altitude)
        self.kalman_plots.update_kalman(self.filter.get_position())

        # length = math.sqrt(lat1 ** 2 + long1 ** 2)
        lat2 = 0.0003 * math.sin(yaw) + self.lat1
        long2 = 0.0003 * math.cos(yaw) + self.long1
        self.kalman_plots.initial_compass_plot.updated([self.lat1, lat2],
                                                       [self.long1, long2])

    def gps_in_range(self):
        if not 280 < self.gps.altitude < 310:
            self.gps.altitude = 300.0
        if -80 < self.gps.longitude_deg < -79.8 and 40.4 < self.gps.latitude_deg < 41 and (
                280 < self.gps.altitude < 310 or self.gps.altitude == 0.0):
            return True
        else:
            return False

    def update_gps_plot(self):
        if self.gps_in_range():
            self.kalman_plots.update_gps(self.gps.latitude_deg,
                                         self.gps.longitude_deg,
                                         self.gps.altitude)
            return True
        else:
            return False

    def update_epoch(self, timestamp):
        if use_filter:
            if self.gps.fix and self.gps.latitude is not None and self.received_fix != self.gps.fix:
                self.received_fix = True
                self.num_recv_from_fix = self.num_received(self.gps)

            if self.num_recv_from_fix is not None and self.num_received(
                    self.gps) - self.num_recv_from_fix == 245:
                self.lat1, self.long1, self.alt1 = self.gps.latitude_deg, self.gps.longitude_deg, self.gps.altitude

            elif self.filter is None and self.num_recv_from_fix is not None and \
                    self.gps_in_range() and self.num_received(self.gps) - self.num_recv_from_fix >= 250:
                if use_filter:
                    self.init_filter(timestamp)

            elif self.filter is not None and self.num_recv_from_fix is not None:
                # if self.num_received(self.gps) % 5 == 0:
                if self.update_gps_plot():
                    if use_filter:
                        self.filter.gps_updated(timestamp - self.gps_t0,
                                                self.gps.latitude_deg,
                                                self.gps.longitude_deg,
                                                self.gps.altitude)
                        self.kalman_plots.update_kalman(
                            self.filter.get_position())
                        self.gps_t0 = timestamp

                        lat1, long1, alt1 = self.filter.get_position()
                        roll, pitch, yaw = self.filter.get_orientation()

                        yaw = -self.imu.euler.x
                        # declination = 9, 19
                        #
                        # self.declination = \
                        #     (declination[0] + declination[1] / 60) * math.pi / 180
                        #
                        # yaw = math.atan2(self.imu.mag.y, self.imu.mag.x)
                        # yaw += self.declination
                        # # Correct for reversed heading
                        # if yaw < 0:
                        #     yaw += 2 * math.pi
                        # # Check for wrap and compensate
                        # elif yaw > 2 * math.pi:
                        #     yaw -= 2 * math.pi

                        # length = math.sqrt(lat1 ** 2 + long1 ** 2)
                        lat2 = 0.0003 * math.sin(math.radians(yaw)) + lat1
                        long2 = 0.0003 * math.cos(math.radians(yaw)) + long1

                        self.kalman_plots.update_compass(
                            lat1, lat2, long1, long2)

                        # print(self.gps.latitude_deg, self.gps.longitude_deg, self.gps.altitude)
                        # if use_filter:
                        # print(self.filter.get_position(), self.filter.properties.estimated_velocity.T.tolist())
                        # print(math.degrees(roll), math.degrees(pitch), math.degrees(yaw))

                    if animate and self.live_plot.should_update():
                        if self.live_plot.plot() is False:
                            return False

    def update_ins(self, timestamp):
        if use_filter and self.filter is not None and self.imu_t0 != timestamp:
            self.filter.imu_updated(timestamp - self.imu_t0,
                                    self.imu.linaccel.x, self.imu.linaccel.y,
                                    self.imu.linaccel.z, self.imu.gyro.x,
                                    self.imu.gyro.y, self.imu.gyro.z)
            self.kalman_plots.update_kalman(self.filter.get_position())

            self.imu_t0 = timestamp

    def update_turret(self, timestamp):
        if not args.includelidar and self.turret.did_cloud_update():
            if self.turret.is_cloud_ready() and self.filter is not None and (
                    self.num_received(self.gps) - self.num_recv_from_fix >
                    250):
                v = self.filter.get_velocity()
                vx = v[0]
                vy = v[1]

                ang_v = self.filter.get_angular(timestamp - self.lidar_t0)[2]
                self.slam.update(timestamp, self.turret.distances,
                                 [vx, vy, ang_v])
                self.lidar_t0 = timestamp
                if animate:
                    self.slam_plots.update(self.slam.mapbytes,
                                           self.slam.get_pos())

                    # print(self.slam.get_pos(), (vx, vy, ang_v))

            if animate and not self.live_plot.plot():
                return False

    # ----- live methods -----
    def packet_received(self, timestamp, whoiam, packet):
        if self.did_receive(self.imu):
            if self.update_ins(timestamp) is False:
                return False
        elif self.did_receive(self.gps):
            if self.update_epoch(timestamp) is False:
                return False
            print(timestamp)
            print(self.gps)
            print(self.imu)
        elif self.did_receive(self.turret):
            if self.update_turret(timestamp) is False:
                return False
        else:
            print(packet)
            # elif self.did_receive(self.steering):# and self.steering.goal_reached:
            # print(self.steering.current_step)

    def loop(self):
        if not simulated:
            if self.joystick is not None:
                if self.steering.calibrated:
                    if self.joystick.axis_updated("left x"):
                        self.steering.set_speed(
                            self.joystick.get_axis("left x"))
                    elif self.joystick.button_updated(
                            "A") and self.joystick.get_button("A"):
                        self.steering.set_position(0)

                if self.joystick.button_updated(
                        "B") and self.joystick.get_button("B"):
                    self.brakes.pull()
                elif self.joystick.button_updated(
                        "X") and self.joystick.get_button("X"):
                    self.brakes.release()
                elif self.joystick.button_updated(
                        "Y") and self.joystick.get_button("Y"):
                    self.record(
                        "checkpoint", "%s\t%s\t%s" %
                        (self.checkpoint_num, self.gps.latitude_deg,
                         self.gps.longitude_deg))
                    if self.gps.latitude_deg is not None and self.gps.longitude_deg is not None:
                        print("checkpoint #%s: %3.6f, %3.6f" %
                              (self.checkpoint_num, self.gps.latitude_deg,
                               self.gps.longitude_deg))
                    self.checkpoint_num += 1
                    print("checkpoint #%s" % self.checkpoint_num)
                    # elif self.joystick.dpad_updated():
                    #     if self.joystick.dpad[1] == 1:
                    #         self.brakes.set_brake(self.brakes.goal_position + 20)
                    #     elif self.joystick.dpad[1] == -1:
                    #         self.brakes.set_brake(self.brakes.goal_position - 20)

    def start(self):
        if animate:
            self.live_plot.start_time(self.start_time)

    # ----- simulator methods -----

    def object_packet(self, timestamp):
        if self.did_receive(self.imu):
            if self.update_ins(timestamp) is False:
                return False
        elif self.did_receive(self.gps):
            if self.update_epoch(timestamp) is False:
                return False
        elif self.did_receive(self.turret):
            if self.update_turret(timestamp) is False:
                return False

    # def user_packet(self, timestamp, packet):
    # if self.did_receive("checkpoint"):
    #     print(timestamp, packet)

    # def command_packet(self, timestamp, packet):
    #     if self.did_receive(self.steering):
    #         print(timestamp, packet)

    def close(self):
        if plots_enabled:
            if not animate:
                self.static_plot.plot()
                self.static_plot.show()
            else:
                if simulated:
                    if not self.error_signalled:
                        print("Finished!")
                        self.live_plot.freeze_plot()

                self.live_plot.close()

        if args.computeslam:
            self.slam.make_image()
class AnimationExample(Robot):
    def __init__(self):
        self.gps_plot = RobotPlot("gps", color="red")
        self.compass_plot = RobotPlot("compass", color="purple")
        self.sticky_compass_plot = RobotPlot("sticky compass", color="gray")

        self.sticky_compass_counter = 0
        self.sticky_compass_skip = 100

        self.accuracy_check_plot = RobotPlotCollection(
            "Animation", self.sticky_compass_plot, self.gps_plot,
            self.compass_plot)

        self.plotter = LivePlotter(
            2,
            self.accuracy_check_plot,
            matplotlib_events=dict(key_press_event=self.key_press))

        self.gps = AdafruitGPS()
        self.imu = BNO055()

        # whoiam IDs were different in the old logs, changing for convenience, please don't do this otherwise!!
        self.gps.whoiam = "gps"
        self.imu.whoiam = "imu"

        # file_name, directory = file_sets["rolls day 3"][0]
        super(AnimationExample, self).__init__(self.imu, self.gps)

        self.compass_angle = 0.0
        self.start_angle = 0.0

        self.link(self.gps, self.receive_gps)
        self.link(self.imu, self.receive_imu)

    def key_press(self, event):
        if event.key == " ":
            self.toggle_pause()
            self.plotter.toggle_pause()

    def receive_gps(self, timestamp, packet, packet_type):
        if self.gps.is_position_valid():
            self.gps_plot.append(self.gps.latitude_deg, self.gps.longitude_deg)

            status = self.plotter.plot()
            if status is not None:
                return status

    def init_compass(self, packet):
        self.compass_angle = math.radians(float(packet)) - math.pi / 2

    def offset_angle(self):
        if self.start_angle is None:
            self.start_angle = -self.imu.euler.z

        return (-self.imu.euler.z + self.start_angle -
                self.compass_angle) % (2 * math.pi)

    def compass_coords(self, angle, length=0.0003):
        lat2 = length * math.sin(angle) + self.gps.latitude_deg
        long2 = length * math.cos(angle) + self.gps.longitude_deg
        return lat2, long2

    def receive_imu(self, timestamp, packet, packet_type):
        if self.gps.is_position_valid():
            angle = self.offset_angle()
            lat2, long2 = self.compass_coords(angle)
            self.compass_plot.update([self.gps.latitude_deg, lat2],
                                     [self.gps.longitude_deg, long2])
            self.plotter.draw_text(self.accuracy_check_plot,
                                   "%0.4f" % angle,
                                   self.gps.latitude_deg,
                                   self.gps.longitude_deg,
                                   text_name="angle text")

            if self.sticky_compass_skip > 0 and self.sticky_compass_counter % self.sticky_compass_skip == 0:
                lat2, long2 = self.compass_coords(angle, length=0.0001)
                self.sticky_compass_plot.append(self.gps.latitude_deg,
                                                self.gps.longitude_deg)
                self.sticky_compass_plot.append(lat2, long2)
                self.sticky_compass_plot.append(self.gps.latitude_deg,
                                                self.gps.longitude_deg)
            self.sticky_compass_counter += 1

    def received(self, timestamp, whoiam, packet, packet_type):
        if self.did_receive("initial compass"):
            self.init_compass(packet)
            print("compass value:", packet)

    def loop(self):
        if self.is_paused:
            status = self.plotter.plot()
            if status is not None:
                return status

    def close(self, reason):
        if reason == "done":
            self.plotter.freeze_plot()
        self.plotter.close()
        print(self.dt())