前面几节博客我们主要讲了机器人的选型、传感器的通讯报文解析,并给大家展示了运动控制的效果。这节博客我们对上位机的控制程序进行介绍。
再来看一下上位机的主界面:
首先我们需要加载必要的Python库函数(可以使用pip安装):
import os, sys
# import pyqtgraph as pg
# import numpy as np
import threading
import serial
# import serial.tools.list_ports
# import array
# import PyQt5
import qdarkstyle
from PyQt5.QtWidgets import *
from PyQt5.QtCore import pyqtSlot, QBasicTimer, Qt, QTimer, Qt, QThread
from PyQt5.QtGui import QImage, QPixmap, QPainter, QPen, QGuiApplication    # 二维图片数据显示
# from PyQt5.QtWidgets import QDialog, QSplashScreen
from PyQt5 import QtWidgets
from PyQT_Form import Ui_Form
# import matplotlib.pyplot as plt
# import numpy as np
# import math
# from mpl_toolkits.mplot3d import Axes3D
# import mpl_toolkits.mplot3d.axes3d as p3
import dev_measure
from inverse_calculation import sign_10_2_16, sign_16_2_10
import argparse
import cv2
import time
import random
import torch.backends.cudnn as cudnn
root_path = os.getcwd()
sys.path.insert(0, root_path+"/obj_detection_yolov5") #这个后面的"/yolov5" 文件夹应该是指向的 yolov5根目录.
from obj_detection_yolov5.utils.datasets import *
from obj_detection_yolov5.utils.utils import *
from obj_detection_yolov5.detect_yolov5 import detect_yolov5_py
# from utils.datasets import *
# from utils.utils import *

使用类定义全局变量:

class global_var():
    """
    定义全局变量
    """
    frame_image_detect = None
    car_207_control_flag = 0        # 自主巡航的运动控制标志位
    car_207_driving_flag = 0        # 车辆加减速控制标志位

目标检测程序(目标识别这块还在完善,现在我们主要介绍运动控制)。

首先,定义类detect_img,用于机器人环境感知,识别目标物体;然后通过上面定义的全局变量global_var.car_207_control_flag进行运动控制。

class detect_img():
    """
    单目相机目标识别算法,用于自主巡航
    识别目标之后,通过定义的全局变量,给车辆底盘发送控制指令
    """
    def __init__(self):
        print("已启动目标识别")
    def run_detect(self):
        self.detect()
    def detect(self, save_img=False):
        while True:
            global_var.car_207_control_flag = 1
            global_var.frame_image_detect = im0

定义上位机界面,初始化惯导数据,开启定时器用于界面中刷新数据等等;具体的介绍已经在代码中进行标注。

class MyPyQT_Form(QtWidgets.QWidget, Ui_Form):
    """
    主界面(人机交互界面)
    """
    def __init__(self):
        super(MyPyQT_Form, self).__init__()
        self.setupUi(self)
        # 初始化IMU数据
        self.imu_roll = 0
        self.imu_pitch = 0
        self.imu_yaw = 0
        self.imu_tt = 0
        # 主界面数据动态刷新(定时器)
        self.timer_plotdata = QTimer(self)
        self.timer_plotdata.timeout.connect(self.plotData)
        self.timer_plotdata.start(20)
        # 主界面图像动态刷新(定时器)
        self.timer_camera_video = QTimer(self)
        self.timer_camera_video.timeout.connect(self.camera_video_qtimer)
        self.timer_camera_video.start(20)
        # 给小车上的STM32 103控制板发送指令,控制电机转动,返回12V 10Ah电量信息
        self.motor_control_auto_flag = False    # 自动控制标志位
        # self.car_207_control_auto()             # yolov5识别算法
        os.system("echo nvidia | sudo -S  chmod 777 /dev/ttyUSB*")
        self.motor_control_pre = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]   # 存储上一帧的车辆速度,对比当前帧速度,避免出现速度阶跃变化


定义数据的显示界面,数据的刷新:

    def plotData(self):
        try:
            # print(str(imu_roll), imu_pitch)
            self.lineEdit.setText(str(self.imu_roll))
            self.lineEdit_2.setText(str(self.imu_pitch))
            self.lineEdit_3.setText(str(self.imu_yaw))
        except:
            print("IMU 在界面上显示 失败")
        try:
            self.label_15.setText(str(self.verticalScrollBar.value()))
        except:
            print("vehicle_chassis 在界面上显示 失败")

从零教你设计ROS试验车(2)中我们已经对惯导数据解析进行过介绍,可以对比一下ROS下的惯导数据解析与直接进行惯导数据解析的区别。

def imu_recv_thread(self):
        while self.imu_serial.isOpen():
            # print("YES")
            # time.sleep(0.002)
            try:
                imu_data = []
                imu_header_1 = []
                imu_header_2 = []
                imu_header_1 = self.imu_serial.read(1)      # 读取一个字节
                if imu_header_1[0] == 0x55:
                    imu_header_2 = self.imu_serial.read(1)
                    if imu_header_2[0] == 0x53:
                        imu_data = self.imu_serial.read(9)
                        imu_angle_sum = imu_data[0] + imu_data[1] + imu_data[2] + imu_data[3] + \
                                        imu_data[4] + imu_data[5] + imu_data[6] + imu_data[7] + \
                                        imu_header_1[0] + imu_header_2[0]
                        imu_angle_sum = imu_angle_sum & 0xff
                        try:
                            if imu_angle_sum == imu_data[8]:
                                imu_roll = ((imu_data[1] << 8) | imu_data[0]) / 32768 * 180
                                imu_pitch = (imu_data[3] << 8 | imu_data[2]) / 32768 * 180
                                imu_yaw = (imu_data[5] << 8 | imu_data[4]) / 32768 * 180
                                imu_tt = (imu_data[7] << 8 | imu_data[6]) / 100
                                # 报文解析IMU角度范围为0~360,实际应该为-180~180
                                if imu_roll > 180:
                                    imu_roll = imu_roll - 360
                                if imu_pitch > 180:
                                    imu_pitch = imu_pitch - 360
                                if imu_yaw > 180:
                                    imu_yaw = imu_yaw - 360
                                self.imu_roll = round(imu_roll, 3)  # 小数点后3位
                                self.imu_pitch = round(imu_pitch, 3)
                                self.imu_yaw = round(imu_yaw, 3)
                        except:
                            print("IMU 校验和 错误")
            except:
                print("IMU 数据读取 错误")

使用python的库函数pyserial打开串口,需要预先定义好串口名称、波特率等参数:

    def open_com(self):
        try:
            os.system("echo nvidia | sudo -S  chmod 777 /dev/ttyUSB*")
        except:
            print("打开liunx串口权限 失败")
        try:
            # IMU串口
            self.imu_serial = serial.Serial('/dev/ttyUSB1', 9600, timeout=0.15)  # com_kou
            if self.imu_serial.isOpen():
                # print('imu_serial 串口已打开')
                self.threading_imu_recv = threading.Thread(target=self.imu_recv_thread) # 开着线程用于读取IMU报文
                self.threading_imu_recv.start()
        except:
            QMessageBox.critical(self, "warning", "IMU 串口打开 出现错误")
        try:
            # 打开车辆底盘运动控制的串口,bps=115200
            self.vehicle_chassis_serial = serial.Serial('/dev/ttyUSB2', 115200, timeout=0.15)  # /dev/ttyUSB0
            if self.vehicle_chassis_serial.isOpen():
                print('car_207_serial 串口已打开')
                # TODO:设置前后左右预定义的速度参数,初始化为0
                self.motor_control_manual = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]    # 手动控制:初始化车辆底盘电机转速,默认为0
                self.motor_control_auto = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]      # 自动控制:初始化车辆底盘电机转速,默认为0
                # 给车辆底盘发送控制指令
                self.timer_car_207_send = QTimer(self)
                self.timer_car_207_send.timeout.connect(self.car_207_send_qtimer)
                self.timer_car_207_send.start(20)  # 设置时间间隔 20 ms
                # 给车辆底盘发送控制指令后,接收返回的数据
                self.timer_car_207_recv = QTimer(self)
                self.timer_car_207_recv.timeout.connect(self.car_207_recv_qtimer)
                self.timer_car_207_recv.start(20)  # 设置时间间隔 20 ms
        except:
            QMessageBox.critical(self, "warning", "car_207 串口打开 出现错误")

 点击急停按钮后,将电机控制程序全部进行初始化:
  def car_207_jiting_ui(self):
        # print("car_207_jiting_ui is ok")
        # self.quit_all(None)
        self.motor_control_manual = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
        self.motor_control_auto = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
        # self.motor_control_pre = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
        self.motor_control_auto_flag = False    # 开启手动模式
        self.verticalScrollBar.setValue(0)


点击自动控制按钮之后,将自主巡航标志位置为True,实现自主巡检:

    def car_207_control_auto_ui(self):
        # print("car_207_control_auto_ui is ok")
        self.motor_control_auto_flag = True                         # 自动巡航标志位为True,标志开启了自主巡航模式
        global_var.car_207_control_flag = 1                         # global_var.car_207_control_flag为小车前进、后退、左转、右转控制,默认1表示前进
        os.system("echo nvidia | sudo -S  chmod 777 /dev/ttyUSB*")  # ubuntu系统开机之后需要给串口权限才能打开

 开启定时器,刷新图像数据:
def camera_video_qtimer(self):
        try:
            self.frame_camera = global_var.frame_image_detect
            
            # print("self.frame_camera", self.frame_camera.shape)
            # 下面程序是使用pyqt显示图像
            if self.frame_camera.ndim == 3:
                self.img_gray = cv2.cvtColor(self.frame_camera, cv2.COLOR_BGR2RGB)
                QImage_Format = QImage.Format_RGB888
            elif self.frame_camera.ndim == 2:
                self.img_gray = cv2.cvtColor(self.frame_camera, cv2.COLOR_BGR2RGB)
                QImage_Format = QImage.Format_Grayscale8
            img = QImage(self.img_gray.flatten(), self.img_gray.shape[1], self.img_gray.shape[0],
                         self.img_gray.strides[0], QImage_Format)
            # img = img.rgbSwapped()    # 红色和蓝色颜色互换
            self.label_17.setPixmap(QPixmap.fromImage(img))
            self.label_17.setScaledContents(True)
        except:
            pass    #print("相机运行出错", "self.success_camera, self.frame_camera, self.height, self.width")



给机器人底盘发送控制指令,控制机器人运动:

    def car_207_send_qtimer(self):
        # print("data_send_flag")
        if self.vehicle_chassis_serial.isOpen():    # 判断串口是否打开
            if self.motor_control_auto_flag:        # 判断是否为自主巡航模式,True为自主巡航、False为手动控制
                self.car_207_control_auto_driving(global_var.car_207_control_flag)  # global_var.car_207_control_flag为自主巡航控制标志位,该行根据自主控制标志位,返回4个电机的转速
                # 当前需要的车辆速度
                motor_font_left = sign_16_2_10((self.motor_control_auto[1] << 8) + (self.motor_control_auto[0]))
                motor_font_right = sign_16_2_10((self.motor_control_auto[3] << 8) + (self.motor_control_auto[2]))
                motor_back_left = sign_16_2_10((self.motor_control_auto[5] << 8) + (self.motor_control_auto[4]))
                motor_back_right = sign_16_2_10((self.motor_control_auto[7] << 8) + (self.motor_control_auto[6]))
                motor_speed_now = [motor_font_left, motor_font_right, motor_back_left, motor_back_right]
                # 上一帧中已发送的车辆速度
                motor_font_left_pre = sign_16_2_10((self.motor_control_pre[1] << 8) + (self.motor_control_pre[0]))
                motor_font_right_pre = sign_16_2_10((self.motor_control_pre[3] << 8) + (self.motor_control_pre[2]))
                motor_back_left_pre = sign_16_2_10((self.motor_control_pre[5] << 8) + (self.motor_control_pre[4]))
                motor_back_right_pre = sign_16_2_10((self.motor_control_pre[7] << 8) + (self.motor_control_pre[6]))
                motor_speed_pre = [motor_font_left_pre, motor_font_right_pre, motor_back_left_pre, motor_back_right_pre]
            else:
                # TODO:控制小车电机转速,避免电机转速呈现阶跃变化
                # 当前需要的车辆速度
                motor_font_left = sign_16_2_10((self.motor_control_manual[1] << 8) + (self.motor_control_manual[0]))
                motor_font_right = sign_16_2_10((self.motor_control_manual[3] << 8) + (self.motor_control_manual[2]))
                motor_back_left = sign_16_2_10((self.motor_control_manual[5] << 8) + (self.motor_control_manual[4]))
                motor_back_right = sign_16_2_10((self.motor_control_manual[7] << 8) + (self.motor_control_manual[6]))
                motor_speed_now = [motor_font_left, motor_font_right, motor_back_left, motor_back_right]
                # 上一帧中已发送的车辆速度
                motor_font_left_pre = sign_16_2_10((self.motor_control_pre[1] << 8) + (self.motor_control_pre[0]))
                motor_font_right_pre = sign_16_2_10((self.motor_control_pre[3] << 8) + (self.motor_control_pre[2]))
                motor_back_left_pre = sign_16_2_10((self.motor_control_pre[5] << 8) + (self.motor_control_pre[4]))
                motor_back_right_pre = sign_16_2_10((self.motor_control_pre[7] << 8) + (self.motor_control_pre[6]))
                motor_speed_pre = [motor_font_left_pre, motor_font_right_pre, motor_back_left_pre, motor_back_right_pre]
            # 电机选择标志位,4个电机,每个电机2个字节
            motor_choose_flag = 0
            motor_control_manual_send = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]    # 这是最终通过串口发送的控制指令
            # 下面的for循环比较相邻两帧报文,防止速度发生阶跃变化 |Speed_A - Speed_B|>5?
            for msn, msp in zip(motor_speed_now, motor_speed_pre):
                if msn >= msp and abs(msn - msp) >= 5:
                    speed_HL = sign_10_2_16(msp + 5)
                    motor_control_manual_send[motor_choose_flag + 1] = (speed_HL >> 8) & 0xff
                    motor_control_manual_send[motor_choose_flag] = speed_HL & 0xff
                elif msn < msp and abs(msn - msp) >= 5:
                    speed_HL = sign_10_2_16(msp - 5)
                    motor_control_manual_send[motor_choose_flag + 1] = (speed_HL >> 8) & 0xff
                    motor_control_manual_send[motor_choose_flag] = speed_HL & 0xff
                else:
                    if self.motor_control_auto_flag:
                        motor_control_manual_send[motor_choose_flag + 1] = self.motor_control_auto[motor_choose_flag + 1]
                        motor_control_manual_send[motor_choose_flag] = self.motor_control_auto[motor_choose_flag]
                    else:
                        motor_control_manual_send[motor_choose_flag + 1] = self.motor_control_manual[motor_choose_flag + 1]
                        motor_control_manual_send[motor_choose_flag] = self.motor_control_manual[motor_choose_flag]
                motor_choose_flag += 2
            # 校验和
            motor_send_check_full = 0xfe + 0xef + 0x08 + \
                                    motor_control_manual_send[1] + motor_control_manual_send[0] + \
                                    motor_control_manual_send[3] + motor_control_manual_send[2] + \
                                    motor_control_manual_send[5] + motor_control_manual_send[4] + \
                                    motor_control_manual_send[7] + motor_control_manual_send[6]
            motor_send_check = motor_send_check_full & 0xff
            # feef08000afff6000afff6f3, FEEF08000800080008000815
            # 最终发送的控制指令
            motor_send = [0xfe, 0xef, 0x08,
                          motor_control_manual_send[1], motor_control_manual_send[0],
                          motor_control_manual_send[3], motor_control_manual_send[2],
                          motor_control_manual_send[5], motor_control_manual_send[4],
                          motor_control_manual_send[7], motor_control_manual_send[6],
                          motor_send_check]
            self.motor_control_pre = motor_control_manual_send
            motor_send_byte = bytes(motor_send)
            self.vehicle_chassis_serial.write(motor_send_byte)
        else:
            print("车辆底盘运动控制 串口打开 (定时器) 失败")


给机器人底盘发送控制指令后,接收返回的数据,主要为12v10ah锂电池信息(这个电池是给机器人底盘单独进行供电):

    def car_207_recv_qtimer(self):
        if self.vehicle_chassis_serial.isOpen():
            try:
                num = self.vehicle_chassis_serial.inWaiting()
                if num > 0:
                    data = self.vehicle_chassis_serial.read(num)
                    data_check = self.vehicle_chassis_motor_recv_check(data)
                    if len(data) == 23 and data[0] == 254 and data[1] == 239 and data_check == data[-1]:
                        self.lineEdit_10.setText((str(data[-4]) + " %"))                                        # 12v10Ah电池电量
                        self.lineEdit_11.setText((str((((data[-3] << 8) + data[-2]) * 100) / 1000)) + " V")     # 12v10Ah电池电压为
            except:
                print("car_207 接收数据 (定时器) 错误")
        else:
            print("self.vehicle_chassis_serial (串口)未打开")

定义自动巡航模式下,前进、后退、左转、右转的运动速度:

    def car_207_control_auto_driving(self, control_flag):
        if control_flag == 1:
            self.motor_control_auto = [12, 0, 12, 0, 12, 0, 12, 0]
        elif control_flag == 2:
            self.motor_control_auto = [244, 255, 244, 255, 244, 255, 244, 255]
        elif control_flag == 3:
            self.motor_control_auto = [12, 0, 244, 255, 12, 0, 244, 255]
        elif control_flag == 4:
            self.motor_control_auto = [244, 255, 12, 0, 244, 255, 12, 0]
        elif control_flag == 0:
            self.motor_control_auto = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

给车辆底盘发送控制指令,并接收返回的数据,对接收的数据进行校验:

    def vehicle_chassis_motor_recv_check(self, motor_recv_data):
        motor_recv_sum = 0
        for i in range(len(motor_recv_data)-1):
            motor_recv_sum += motor_recv_data[i]
        return motor_recv_sum & 0xff

手动模式下,车辆前进、后退、左转、右转的控制:

    def car_207_go_forward_ui(self):
        self.motor_control_auto_flag = False  # 自动控制标志位
        self.motor_control_manual = [int(self.verticalScrollBar.value()), 0x00,
                                     int(self.verticalScrollBar.value()), 0x00,
                                     int(self.verticalScrollBar.value()), 0x00,
                                     int(self.verticalScrollBar.value()), 0x00]




    def car_207_go_back_ui(self):
        self.motor_control_auto_flag = False  # 自动控制标志位
        send_back_data = sign_10_2_16(-int(self.verticalScrollBar.value()))
        self.motor_control_manual = [send_back_data & 0xff, (send_back_data >> 8) & 0xff,
                                     send_back_data & 0xff, (send_back_data >> 8) & 0xff,
                                     send_back_data & 0xff, (send_back_data >> 8) & 0xff,
                                     send_back_data & 0xff, (send_back_data >> 8) & 0xff]




    def car_207_turn_left_ui(self):
        self.motor_control_auto_flag = False  # 自动控制标志位
        send_back_data = sign_10_2_16(-int(self.verticalScrollBar.value()))
        if int(self.verticalScrollBar.value()) > 12:  # 左转速度12:[10, 0, 246, 255, 10, 0, 246, 255]
            self.motor_control_manual = [0x0A, 0x00,
                                         0xF6, 0xFF,
                                         0x0A, 0x00,
                                         0xF6, 0xFF,]
        else:
            self.motor_control_manual = [int(self.verticalScrollBar.value()), 0x00,
                                         send_back_data & 0xff, (send_back_data >> 8) & 0xff,
                                         int(self.verticalScrollBar.value()), 0x00,
                                         send_back_data & 0xff, (send_back_data >> 8) & 0xff]




    def car_207_turn_right_ui(self):
        self.motor_control_auto_flag = False  # 自动控制标志位
        send_back_data = sign_10_2_16(-int(self.verticalScrollBar.value()))
        if int(self.verticalScrollBar.value()) > 12:    # 右转速度12:[246, 255, 10, 0, 246, 255, 10, 0]
            self.motor_control_manual = [0xF6, 0xFF,
                                         0x0A, 0x00,
                                         0xF6, 0xFF,
                                         0x0A, 0x00,]
        else:
            self.motor_control_manual = [send_back_data & 0xff, (send_back_data >> 8) & 0xff,
                                         int(self.verticalScrollBar.value()), 0x00,
                                         send_back_data & 0xff, (send_back_data >> 8) & 0xff,
                                         int(self.verticalScrollBar.value()), 0x00]

退出所有的线程、定时器,初始化标志位等操作:

    def quit_all(self, quit_sign):
        try:
            try:
                self.stop_thread(self.threading_imu_recv)
            except:
                print("threading_imu_recv (线程) 关闭失败")
            self.imu_serial.close()
        except:
            print("imu_serial (串口)关闭失败")
        try:
            self.timer_plotData.stop()
        except:
            print("界面数据刷新(定时器) 关闭失败")
        try:
            self.stop_thread(self.threading_imu_drawing)
        except:
            print("关闭IMU绘图(线程) 关闭失败")
        try:
            try:
                self.timer_car_207_recv.stop()
                self.timer_car_207_send.stop()
            except:
                print("timer_car_207_send(定时器) 关闭失败")
            self.vehicle_chassis_serial.close()
            self.motor_control_auto_flag = False  # 开启手动模式
        except:
            print("vehicle_chassis_serial(串口) 关闭失败")
        try:
            self.timer_camera_video.stop()
        except:
            print("timer_camera_video(定时器) 关闭失败")

python停止线程:

    def stop_thread(self, thread):
        self._async_raise(thread.ident, SystemExit)
    def closeEvent(self, event):
        reply = QtWidgets.QMessageBox.question(self,
                                               '本程序',
                                               "是否要退出程序?",
                                               QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                                               QtWidgets.QMessageBox.No)
        if reply == QtWidgets.QMessageBox.Yes:
            event.accept()
            self.quit_all(None)
            os._exit(0)
        else:
            event.ignore()

定义启动程序:

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    app.setStyleSheet(qdarkstyle.load_stylesheet())     # 使用开源插件优化界面(黑色风格)
    my_pyqt_form = MyPyQT_Form()
    my_pyqt_form.show()
    # TODO:适配TX2,在此处开启线程,用于加载图像识别算法(YOLO-v5)
    with torch.no_grad():
        image_detect = detect_img()
        threading_detect_img = threading.Thread(target=image_detect.run_detect)
        threading_detect_img.start()
    sys.exit(app.exec_())


将下面程序复制到创建的PyQT_Form.py文件中:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'PyQT_Form.ui'
#
# Created by: PyQt5 UI code generator 5.14.1
#
# WARNING! All changes made in this file will be lost!


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(1595, 845)
        self.gridLayout = QtWidgets.QGridLayout(Form)
        self.gridLayout.setContentsMargins(0, 0, 0, -1)
        self.gridLayout.setSpacing(0)
        self.gridLayout.setObjectName("gridLayout")
        self.stackedWidget = QtWidgets.QStackedWidget(Form)
        self.stackedWidget.setStyleSheet("")
        self.stackedWidget.setObjectName("stackedWidget")
        self.page = QtWidgets.QWidget()
        self.page.setObjectName("page")
        self.stackedWidget.addWidget(self.page)
        self.page_2 = QtWidgets.QWidget()
        self.page_2.setObjectName("page_2")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.page_2)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label_17 = QtWidgets.QLabel(self.page_2)
        font = QtGui.QFont()
        font.setPointSize(100)
        self.label_17.setFont(font)
        self.label_17.setAlignment(QtCore.Qt.AlignCenter)
        self.label_17.setObjectName("label_17")
        self.horizontalLayout.addWidget(self.label_17)
        self.groupBox_2 = QtWidgets.QGroupBox(self.page_2)
        self.groupBox_2.setMinimumSize(QtCore.QSize(200, 0))
        self.groupBox_2.setMaximumSize(QtCore.QSize(200, 16777215))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.groupBox_2.setFont(font)
        self.groupBox_2.setObjectName("groupBox_2")
        self.groupBox_4 = QtWidgets.QGroupBox(self.groupBox_2)
        self.groupBox_4.setGeometry(QtCore.QRect(10, 441, 181, 120))
        self.groupBox_4.setMinimumSize(QtCore.QSize(0, 120))
        self.groupBox_4.setMaximumSize(QtCore.QSize(181, 120))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.groupBox_4.setFont(font)
        self.groupBox_4.setObjectName("groupBox_4")
        self.label_10 = QtWidgets.QLabel(self.groupBox_4)
        self.label_10.setGeometry(QtCore.QRect(10, 70, 51, 31))
        font = QtGui.QFont()
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_10.setFont(font)
        self.label_10.setObjectName("label_10")
        self.lineEdit_10 = QtWidgets.QLineEdit(self.groupBox_4)
        self.lineEdit_10.setGeometry(QtCore.QRect(70, 70, 91, 31))
        self.lineEdit_10.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_10.setFont(font)
        self.lineEdit_10.setObjectName("lineEdit_10")
        self.lineEdit_11 = QtWidgets.QLineEdit(self.groupBox_4)
        self.lineEdit_11.setGeometry(QtCore.QRect(70, 30, 91, 31))
        self.lineEdit_11.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_11.setFont(font)
        self.lineEdit_11.setObjectName("lineEdit_11")
        self.label_11 = QtWidgets.QLabel(self.groupBox_4)
        self.label_11.setGeometry(QtCore.QRect(10, 30, 54, 31))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.label_11.setFont(font)
        self.label_11.setObjectName("label_11")
        self.groupBox_5 = QtWidgets.QGroupBox(self.groupBox_2)
        self.groupBox_5.setGeometry(QtCore.QRect(10, 570, 181, 120))
        self.groupBox_5.setMinimumSize(QtCore.QSize(0, 120))
        self.groupBox_5.setMaximumSize(QtCore.QSize(200, 100))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.groupBox_5.setFont(font)
        self.groupBox_5.setObjectName("groupBox_5")
        self.lineEdit_12 = QtWidgets.QLineEdit(self.groupBox_5)
        self.lineEdit_12.setGeometry(QtCore.QRect(70, 70, 91, 31))
        self.lineEdit_12.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_12.setFont(font)
        self.lineEdit_12.setObjectName("lineEdit_12")
        self.label_12 = QtWidgets.QLabel(self.groupBox_5)
        self.label_12.setGeometry(QtCore.QRect(10, 70, 51, 31))
        font = QtGui.QFont()
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_12.setFont(font)
        self.label_12.setObjectName("label_12")
        self.lineEdit_13 = QtWidgets.QLineEdit(self.groupBox_5)
        self.lineEdit_13.setGeometry(QtCore.QRect(70, 30, 91, 31))
        self.lineEdit_13.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_13.setFont(font)
        self.lineEdit_13.setObjectName("lineEdit_13")
        self.label_13 = QtWidgets.QLabel(self.groupBox_5)
        self.label_13.setGeometry(QtCore.QRect(10, 30, 51, 31))
        font = QtGui.QFont()
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_13.setFont(font)
        self.label_13.setObjectName("label_13")
        self.pushButton_6 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_6.setGeometry(QtCore.QRect(10, 704, 181, 50))
        self.pushButton_6.setMinimumSize(QtCore.QSize(0, 50))
        font = QtGui.QFont()
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.pushButton_6.setFont(font)
        self.pushButton_6.setObjectName("pushButton_6")
        self.pushButton = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton.setGeometry(QtCore.QRect(10, 760, 181, 50))
        self.pushButton.setMinimumSize(QtCore.QSize(0, 50))
        font = QtGui.QFont()
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.groupBox = QtWidgets.QGroupBox(self.groupBox_2)
        self.groupBox.setGeometry(QtCore.QRect(10, 30, 181, 403))
        self.groupBox.setMinimumSize(QtCore.QSize(0, 0))
        self.groupBox.setMaximumSize(QtCore.QSize(200, 420))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.groupBox.setFont(font)
        self.groupBox.setObjectName("groupBox")
        self.lineEdit = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit.setGeometry(QtCore.QRect(70, 30, 91, 31))
        self.lineEdit.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit.setFont(font)
        self.lineEdit.setObjectName("lineEdit")
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(10, 30, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.groupBox)
        self.label_2.setGeometry(QtCore.QRect(10, 70, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.groupBox)
        self.label_3.setGeometry(QtCore.QRect(10, 110, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_2.setGeometry(QtCore.QRect(70, 70, 91, 31))
        self.lineEdit_2.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_2.setFont(font)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.lineEdit_3 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_3.setGeometry(QtCore.QRect(70, 110, 91, 31))
        self.lineEdit_3.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_3.setFont(font)
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.lineEdit_4 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_4.setGeometry(QtCore.QRect(70, 230, 91, 31))
        self.lineEdit_4.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_4.setFont(font)
        self.lineEdit_4.setObjectName("lineEdit_4")
        self.label_4 = QtWidgets.QLabel(self.groupBox)
        self.label_4.setGeometry(QtCore.QRect(10, 190, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.lineEdit_6 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_6.setGeometry(QtCore.QRect(70, 190, 91, 31))
        self.lineEdit_6.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_6.setFont(font)
        self.lineEdit_6.setObjectName("lineEdit_6")
        self.label_6 = QtWidgets.QLabel(self.groupBox)
        self.label_6.setGeometry(QtCore.QRect(10, 150, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")
        self.label_5 = QtWidgets.QLabel(self.groupBox)
        self.label_5.setGeometry(QtCore.QRect(10, 230, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.lineEdit_5 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_5.setGeometry(QtCore.QRect(70, 150, 91, 31))
        self.lineEdit_5.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_5.setFont(font)
        self.lineEdit_5.setObjectName("lineEdit_5")
        self.label_7 = QtWidgets.QLabel(self.groupBox)
        self.label_7.setGeometry(QtCore.QRect(10, 310, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_7.setFont(font)
        self.label_7.setObjectName("label_7")
        self.lineEdit_7 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_7.setGeometry(QtCore.QRect(70, 310, 91, 31))
        self.lineEdit_7.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_7.setFont(font)
        self.lineEdit_7.setObjectName("lineEdit_7")
        self.label_8 = QtWidgets.QLabel(self.groupBox)
        self.label_8.setGeometry(QtCore.QRect(10, 270, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_8.setFont(font)
        self.label_8.setObjectName("label_8")
        self.label_9 = QtWidgets.QLabel(self.groupBox)
        self.label_9.setGeometry(QtCore.QRect(10, 350, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(15)
        font.setBold(False)
        font.setWeight(50)
        self.label_9.setFont(font)
        self.label_9.setObjectName("label_9")
        self.lineEdit_8 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_8.setGeometry(QtCore.QRect(70, 270, 91, 31))
        self.lineEdit_8.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_8.setFont(font)
        self.lineEdit_8.setObjectName("lineEdit_8")
        self.lineEdit_9 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_9.setGeometry(QtCore.QRect(70, 350, 91, 31))
        self.lineEdit_9.setMinimumSize(QtCore.QSize(80, 0))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.lineEdit_9.setFont(font)
        self.lineEdit_9.setObjectName("lineEdit_9")
        self.horizontalLayout.addWidget(self.groupBox_2)
        self.stackedWidget_2 = QtWidgets.QStackedWidget(self.page_2)
        self.stackedWidget_2.setMaximumSize(QtCore.QSize(320, 16777215))
        self.stackedWidget_2.setObjectName("stackedWidget_2")
        self.page_7 = QtWidgets.QWidget()
        self.page_7.setObjectName("page_7")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.page_7)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.widget_4 = QtWidgets.QWidget(self.page_7)
        self.widget_4.setMaximumSize(QtCore.QSize(330, 16777215))
        self.widget_4.setObjectName("widget_4")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget_4)
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.widget_5 = QtWidgets.QWidget(self.widget_4)
        self.widget_5.setMaximumSize(QtCore.QSize(110, 16777215))
        self.widget_5.setObjectName("widget_5")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.widget_5)
        self.verticalLayout.setObjectName("verticalLayout")
        self.label_15 = QtWidgets.QLabel(self.widget_5)
        self.label_15.setMaximumSize(QtCore.QSize(16777215, 30))
        font = QtGui.QFont()
        font.setFamily("黑体")
        font.setPointSize(15)
        self.label_15.setFont(font)
        self.label_15.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.label_15.setAlignment(QtCore.Qt.AlignCenter)
        self.label_15.setObjectName("label_15")
        self.verticalLayout.addWidget(self.label_15)
        self.verticalScrollBar = QtWidgets.QScrollBar(self.widget_5)
        self.verticalScrollBar.setMinimumSize(QtCore.QSize(70, 0))
        self.verticalScrollBar.setMaximumSize(QtCore.QSize(90, 16777215))
        self.verticalScrollBar.setMaximum(99)
        self.verticalScrollBar.setOrientation(QtCore.Qt.Vertical)
        self.verticalScrollBar.setInvertedAppearance(True)
        self.verticalScrollBar.setObjectName("verticalScrollBar")
        self.verticalLayout.addWidget(self.verticalScrollBar)
        self.horizontalLayout_3.addWidget(self.widget_5)
        self.widget_6 = QtWidgets.QWidget(self.widget_4)
        self.widget_6.setMinimumSize(QtCore.QSize(150, 0))
        self.widget_6.setMaximumSize(QtCore.QSize(180, 16777215))
        self.widget_6.setStyleSheet("")
        self.widget_6.setObjectName("widget_6")
        self.pushButton_5 = QtWidgets.QPushButton(self.widget_6)
        self.pushButton_5.setGeometry(QtCore.QRect(10, 280, 150, 80))
        self.pushButton_5.setMinimumSize(QtCore.QSize(150, 80))
        self.pushButton_5.setMaximumSize(QtCore.QSize(150, 80))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.pushButton_5.setFont(font)
        self.pushButton_5.setObjectName("pushButton_5")
        self.pushButton_2 = QtWidgets.QPushButton(self.widget_6)
        self.pushButton_2.setGeometry(QtCore.QRect(10, 10, 150, 80))
        self.pushButton_2.setMinimumSize(QtCore.QSize(150, 80))
        self.pushButton_2.setMaximumSize(QtCore.QSize(150, 80))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.pushButton_2.setFont(font)
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.widget_6)
        self.pushButton_3.setGeometry(QtCore.QRect(10, 100, 150, 80))
        self.pushButton_3.setMinimumSize(QtCore.QSize(150, 80))
        self.pushButton_3.setMaximumSize(QtCore.QSize(150, 80))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.pushButton_3.setFont(font)
        self.pushButton_3.setObjectName("pushButton_3")
        self.pushButton_4 = QtWidgets.QPushButton(self.widget_6)
        self.pushButton_4.setGeometry(QtCore.QRect(10, 190, 150, 80))
        self.pushButton_4.setMinimumSize(QtCore.QSize(150, 80))
        self.pushButton_4.setMaximumSize(QtCore.QSize(150, 80))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.pushButton_4.setFont(font)
        self.pushButton_4.setObjectName("pushButton_4")
        self.pushButton_7 = QtWidgets.QPushButton(self.widget_6)
        self.pushButton_7.setGeometry(QtCore.QRect(10, 460, 150, 150))
        self.pushButton_7.setMinimumSize(QtCore.QSize(150, 150))
        self.pushButton_7.setMaximumSize(QtCore.QSize(150, 150))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.pushButton_7.setFont(font)
        self.pushButton_7.setStyleSheet("background-color: rgb(170, 0, 0);")
        self.pushButton_7.setObjectName("pushButton_7")
        self.pushButton_8 = QtWidgets.QPushButton(self.widget_6)
        self.pushButton_8.setGeometry(QtCore.QRect(10, 370, 150, 80))
        self.pushButton_8.setMinimumSize(QtCore.QSize(150, 80))
        self.pushButton_8.setMaximumSize(QtCore.QSize(150, 80))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.pushButton_8.setFont(font)
        self.pushButton_8.setObjectName("pushButton_8")
        self.horizontalLayout_3.addWidget(self.widget_6)
        self.gridLayout_2.addWidget(self.widget_4, 0, 0, 1, 1)
        self.stackedWidget_2.addWidget(self.page_7)
        self.page_8 = QtWidgets.QWidget()
        self.page_8.setObjectName("page_8")
        self.stackedWidget_2.addWidget(self.page_8)
        self.horizontalLayout.addWidget(self.stackedWidget_2)
        self.stackedWidget.addWidget(self.page_2)
        self.gridLayout.addWidget(self.stackedWidget, 0, 0, 1, 1)

        self.retranslateUi(Form)
        self.stackedWidget.setCurrentIndex(1)
        self.pushButton.clicked.connect(Form.imu_drawing)
        self.pushButton_2.clicked.connect(Form.car_207_go_forward_ui)
        self.pushButton_3.clicked.connect(Form.car_207_go_back_ui)
        self.pushButton_4.clicked.connect(Form.car_207_turn_left_ui)
        self.pushButton_5.clicked.connect(Form.car_207_turn_right_ui)
        self.pushButton_6.clicked.connect(Form.open_com)
        self.pushButton_7.clicked.connect(Form.car_207_jiting_ui)
        self.pushButton_8.clicked.connect(Form.car_207_control_auto_ui)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "TX2 Host Computer"))
        self.label_17.setText(_translate("Form", "SENSOR"))
        self.groupBox_2.setTitle(_translate("Form", "SENSOR"))
        self.groupBox_4.setTitle(_translate("Form", "12V10Ah"))
        self.label_10.setText(_translate("Form", "ELE:"))
        self.lineEdit_10.setText(_translate("Form", "0"))
        self.lineEdit_11.setText(_translate("Form", "0"))
        self.label_11.setText(_translate("Form", "VOL:"))
        self.groupBox_5.setTitle(_translate("Form", "12V20Ah"))
        self.lineEdit_12.setText(_translate("Form", "0"))
        self.label_12.setText(_translate("Form", "ELE:"))
        self.lineEdit_13.setText(_translate("Form", "0"))
        self.label_13.setText(_translate("Form", "VOL:"))
        self.pushButton_6.setText(_translate("Form", "打开串口"))
        self.pushButton.setText(_translate("Form", "绘图IMU"))
        self.groupBox.setTitle(_translate("Form", "IMU"))
        self.lineEdit.setText(_translate("Form", "0"))
        self.label.setText(_translate("Form", "Roll:"))
        self.label_2.setText(_translate("Form", "Pitch:"))
        self.label_3.setText(_translate("Form", "Yaw:"))
        self.lineEdit_2.setText(_translate("Form", "0"))
        self.lineEdit_3.setText(_translate("Form", "0"))
        self.lineEdit_4.setText(_translate("Form", "0"))
        self.label_4.setText(_translate("Form", "v(P):"))
        self.lineEdit_6.setText(_translate("Form", "0"))
        self.label_6.setText(_translate("Form", "v(R):"))
        self.label_5.setText(_translate("Form", "v(Y):"))
        self.lineEdit_5.setText(_translate("Form", "0"))
        self.label_7.setText(_translate("Form", "a(P):"))
        self.lineEdit_7.setText(_translate("Form", "0"))
        self.label_8.setText(_translate("Form", "a(R):"))
        self.label_9.setText(_translate("Form", "a(Y):"))
        self.lineEdit_8.setText(_translate("Form", "0"))
        self.lineEdit_9.setText(_translate("Form", "0"))
        self.label_15.setText(_translate("Form", "0"))
        self.pushButton_5.setText(_translate("Form", "原地右转"))
        self.pushButton_2.setText(_translate("Form", "前进"))
        self.pushButton_3.setText(_translate("Form", "后退"))
        self.pushButton_4.setText(_translate("Form", "原地左转"))
        self.pushButton_7.setText(_translate("Form", "急停"))
        self.pushButton_8.setText(_translate("Form", "自动控制"))