def waypoint_manager(self):
        if self._distance < 2:
            if self._curr_waypoint_num < self._waypoints_num:
                try:
                    self._curr_waypoint_num += 1
                    self._next_waypoint = self._waypoints[
                        self._curr_waypoint_num]
                    msg = "Waypoint reached, heading to #{0} at {1}\n".format(
                        str(self._curr_waypoint_num + 1),
                        str(self._next_waypoint))
                    cmd.send_uart(msg, log_flag)
                    msg = {
                        "type": "gps",
                        "func": "next_waypoint",
                        "index": str(self._curr_waypoint_num + 1)
                    }
                    msg = ujson.dump(msg)
                    cmd.send_uart(msg, log_flag)
                    return True
                except IndexError:
                    cmd.send_uart("Waypoint manager IndexError\n", log_flag)
                    return False

            else:
                cmd.send_uart("All waypoints have been covered", log_flag)
                self.stop_planner()
                msg = {"type": "gps", "func": "next_waypoint", "index": -1}
                msg = ujson.dump(msg)
                cmd.send_uart(msg, log_flag)
                return False
        else:
            return True
 def resume_planner(self):
     if self._planner_init is True:
         global_variables.pid_test.start_update()
         cmd.send_uart("Autonomous mode resumed\n", log_flag)
     else:
         cmd.send_uart("Autonomous mode hasn't been started yet\n",
                       log_flag)
Beispiel #3
0
    def gps_data(self):
        try:
            msg = {
                "type": "gps",
                "func": "position",
                "lat": "{:.7f}".format(self.latitude),
                "long": "{:.7f}".format(self.longitude),
                "hdop": str(self.hdop),
                "speed": "{:.2f}".format(self.speed)
            }
        except ValueError:
            msg = {
                "type": "gps",
                "func": "position",
                "lat": str(self.latitude),
                "long": str(self.longitude),
                "hdop": str(self.hdop),
                "speed": str(self.speed)
            }

        msg = ujson.dumps(msg)

        cmd.send_uart(msg, log_flag)
        if debug_flag is True:
            cmd.debug(msg, debug_flag)
Beispiel #4
0
 def start_update(self):
     # 16-bit timer
     self.timer = Timer(9)
     self.timer.init(freq=100)
     self.timer.callback(self.update)
     self.enable = True
     self.error_sum = 0
     cmd.send_uart("PID timers started\n", log_flag)
 def pause_planner(self):
     if self._planner_init is True:
         self.status = "Pause"
         global_variables.pid_test.stop_update()
         cmd.send_uart("Autonomous mode paused\n", log_flag)
     else:
         cmd.send_uart("Autonomous mode hasn't been started yet\n",
                       log_flag)
 def waypoint_add(self, start):
     if start is True:
         self._waypoints.clear()
     else:
         cmd.send_uart(
             "{0:d} waypoints added\n".format(len(self._waypoints)),
             log_flag)
     self._add = start
 def waypoint_coord(self, waypoint):
     if self._add is True:
         try:
             self._waypoints.append(
                 (float(waypoint[0]), float(waypoint[1])))
         except ValueError:
             cmd.send_uart("Invalid coordinate format", log_flag)
             print(waypoint[0], waypoint[1])
Beispiel #8
0
 def stop_update(self):
     try:
         self.timer.deinit()
     except AttributeError:
         cmd.send_uart("PID not initialised\n", log_flag)
     self.enable = False
     self.error_sum = 0
     motor.motor_abs(("l", 0), ("r", 0))
     cmd.send_uart("PID stopped\n", log_flag)
 def stop_planner(self):
     self.status = "Stop"
     global_variables.pid_test.stop_update()
     self._distance = None
     self._curr_waypoint_num = 0
     self._waypoints.clear()
     self._next_waypoint = (None, None)
     self._bearing = None
     self._planner_init = False
     cmd.send_uart("Autonomous mode stopped\n", log_flag)
    def planner_data(self):
        msg = {
            "type": "gps",
            "func": "planner",
            "stat": str(self.status),
            "tar_head": str(self._bearing),
            "way_num": str(self._curr_waypoint_num + 1),
            "next_way_lat": str(self._next_waypoint[0]),
            "next_way_lon": str(self._next_waypoint[1]),
            "way_dist": str(self._distance)
        }
        msg = ujson.dumps(msg)

        cmd.send_uart(msg, log_flag)
        if debug_flag is True:
            cmd.debug(msg, debug_flag)
 def dist_bearing(self):
     if ((self._gps.pos_fix > 0) or
         (self._gps.status == "A")) and self._gps.latitude is not None:
         self._current_pos = (float(self._gps.latitude),
                              float(self._gps.longitude))
         try:
             # A is current_pos in rad, B is next_waypoint in rad
             A = ([0.0174533 * x for x in self._current_pos])
             B = ([0.0174533 * x for x in self._next_waypoint])
             d_long = float(B[1] - A[1])
             # This is true North heading
             self._bearing = math.atan2(
                 (math.sin(d_long) * math.cos(B[0])),
                 (math.cos(A[0]) * math.sin(B[0]) - math.sin(A[0]) *
                  math.cos(B[0]) * math.cos(d_long))) * 57.29577951
             if self._bearing > 180:
                 self._bearing -= 360
             # Distance calculated using the haversine formula
             # Earth's mean radius in m
             R = 6371000
             d_lat = float(B[0] - A[0])
             a = math.sin(d_lat / 2)**2 + math.cos(A[0]) * math.cos(
                 B[0]) * math.sin(d_long / 2)**2
             c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
             self._distance = R * c
             self.i = 0
             # Updates waypoints if robot has reached waypoint
             flag = self.waypoint_manager()
             if flag:
                 return True, (self._distance, self._bearing)
             else:
                 return False, (None, None)
         except TypeError:
             if self.i > 5:
                 cmd.send_uart("Inaccurate hdop in dist_bearing", log_flag)
                 self.pause_planner()
             self.i += 1
             return False, (None, None)
     else:
         if self.i > 5:
             cmd.send_uart("Inaccurate pos in dist_bearing", log_flag)
             self.pause_planner()
         self.i += 1
         return False, (None, None)
Beispiel #12
0
def init():
    global uart
    # Initialising UART6 (Y1, Y2)
    uart = UART(6, baudrate=38400, timeout=10, read_buf_len=200)
    pyb.repl_uart(uart)
    print('RPi UART setup')

    global uart_gps
    global gps_device
    global gps_planner
    uart_gps = UART(4, baudrate=9600, timeout=10, read_buf_len=600)
    gps_device = gps.GPS(uart_gps)
    gps_planner = planner.PLANNER(gps_device)
    print("GPS set up")

    global pid_test
    pid_test = pid.PID(0.3, 0, 0.1, gps_planner.dist_bearing, 1)

    # If True, uart messages are sent back normally,
    # if false, only log messages are sent back.
    global UART_comms_master
    UART_comms_master = False

    global imu, fuse, i2c
    global imu_acc, imu_gyr, imu_mag

    i2c = I2C(scl=Pin('Y9'), sda=Pin('Y10'))
    try:
        imu = MPU9250(i2c, scaling=(-1, -1, -1))
        imu._mag.cal = (20.915039062, 11.880468750, 23.293359375)
        imu.gyro_filter_range = 4
        imu.accel_filter_range = 4
        print(imu.mag.cal)
        print(imu.accel.cal)
        print(imu.gyro.cal)
        mpu_addr = "MPU9250 id: {:X}".format(imu.mpu_addr)
        cmd.send_uart(mpu_addr, True)
        fuse = Fusion()
    except:
        cmd.send_uart("No imu detected", True)

    sensors.ina_init(i2c)
 def go_home(self):
     if self._planner_init is True:
         self.status = "Start"
         self._waypoints = [self._home]
         self._next_waypoint = self._home
         self._waypoints_num = 1
         self._curr_waypoint_num = 1
         self.resume_planner()
         msg = {
             "type": "gps",
             "func": "waypoints",
             "waypoints": self._waypoints
         }
         msg = ujson.dumps(msg)
         cmd.send_uart(msg, log_flag)
         if debug_flag is True:
             cmd.debug(msg, debug_flag)
     else:
         cmd.send_uart("Autonomous mode hasn't been started yet\n",
                       log_flag)
Beispiel #14
0
    def pid(self):
        # Updating the target variable
        if self.target_flag is True:
            # t_fn is planner.dist_bearing()
            flag, (dist, bear) = self.t_fn()
            self.target_flag = False
            if flag is True:
                self.target = bear
            else:
                return False

        self.feedback = global_variables.fuse.heading

        # Error term
        self.error = self.target - self.feedback
        # Always rotating in the shortest direction
        if self.error > 180:
            self.error = 360 - self.error
        elif self.error < -180:
            self.error = 360 + self.error
        if (self.error > -20) and (self.error < 20):
            self.error_sum += self.error
        self.pid_out = self.Kp * self.error  # Proportional
        self.pid_out += self.Kd * self.prev_error  # Derivative
        self.pid_out += self.Ki * self.error_sum  # Integral
        self.prev_error = self.error

        self.base(self.error)
        # If error is negative (left turn needed to reduce error), so is pid_out. right speed increases, left speed decreases, vice versa
        self.output = (round(
            ((self.base_speed + self.pid_out / 2) * self.LIMITER),
            0), round(((self.base_speed - self.pid_out / 2) * self.LIMITER),
                      0))
        if (abs(self.output[0]) < self.POWER_LIMIT) and (abs(self.output[1]) <
                                                         self.POWER_LIMIT):
            motor.motor_abs(("l", self.output[0]), ("r", self.output[1]))
        else:
            cmd.send_uart("pid out of range\n", log_flag)
            self.error_sum = 0
        return True
Beispiel #15
0
 def start_pid(self):
     # Allows time for the first IMU reading to be completed
     sleep_ms(12)
     cmd.send_uart("PID thread started", True)
     print("PID thread started")
     self.enable = False
     i = 0
     while True:
         if i % 5 == 0:
             if self.enable:
                 self.pid()
         if i % 3 == 0:
             try:
                 acc = global_variables.imu.accel.xyz
                 gyr = global_variables.imu.gyro.xyz
                 mag = global_variables.imu.mag.xyz
             except:
                 cmd.send_uart("MPU reading error", log_flag)
         if i % 300 == 0:
             msg = {
                 "type": "gps",
                 "func": "heading",
                 "head": str(global_variables.fuse.heading)
             }
             msg = ujson.dumps(msg)
             cmd.send_uart(msg, log_flag)
             # print(global_variables.fuse.heading)
         global_variables.fuse.update(acc, gyr, mag)
         i += 1
 def start_planner(self):
     try:
         if ((self._gps.pos_fix > 0) or
             (self._gps.status == "A")) and self._gps.latitude is not None:
             if self._planner_init is False:
                 if self.waypoint_init() is True:
                     self.status = "Start"
                     global_variables.pid_test.start_update()
                     cmd.send_uart("Autonomous mode started\n", log_flag)
                     self._planner_init = True
                 else:
                     cmd.send_uart("Couldn't initialise waypoints\n",
                                   log_flag)
             else:
                 self.status = "Start"
                 self.resume_planner()
         else:
             cmd.send_uart("GPS accuracy not good enough\n", log_flag)
     except TypeError:
         cmd.send_uart("No GPS signal\n", log_flag)
 def waypoint_init(self):
     try:
         self._waypoints_num = len(self._waypoints) - 1
         self._home = self._waypoints[0]
         self._curr_waypoint_num = 0
         self._next_waypoint = self._waypoints[0]
         cmd.send_uart(
             "{0:d} waypoints initialised\n".format(len(self._waypoints)),
             log_flag)
         msg = {
             "type": "gps",
             "func": "waypoints",
             "waypoints": self._waypoints
         }
         msg = ujson.dumps(msg)
         cmd.send_uart(msg, log_flag)
         if debug_flag is True:
             cmd.debug(msg, debug_flag)
         return True
     except (TypeError, IndexError):
         cmd.send_uart("No waypoints", log_flag)
         return False
Beispiel #18
0
 def print_msg(self):
     msg = self._uart.readline()
     if msg is not None:
         cmd.send_uart(msg, log_flag)