PyQt6 QThread 错误 malloc():未排序的双链表损坏、双释放或损坏 (!prev)

问题描述 投票:0回答:1

我发现当我从 QThread 访问 gui 时,出现 QTimer 错误。我看到一个解决方案说使用 pyqtSignal 解决了它。一开始,它实际上运作良好。 但是,当我添加代码时,出现了一些错误,我无法弄清楚问题发生在哪里。

from PyQt6.QtWidgets import *
import sys
import math
from PyQt6.QtCore import *
from PyQt6.QtGui import QPixmap, QColor, QPen
import mainbot_control_ui.submodule.control_ui as control_ui
import mainbot_control_ui.submodule.publisher as pub
import mainbot_control_ui.submodule.subscriber as sub
import rclpy
from sensor_msgs.msg import Imu, LaserScan

MOVING_LOG_SIZE = 100
MAP_X_SIZE=500
MAP_Y_SIZE=500


class ros_Tread1(QThread):
    def __init__(self):
        super().__init__()

    def run(self):
        while rclpy.ok():
            try:
                rclpy.spin_once(sub_angvel_node, timeout_sec=0.01)
                rclpy.spin_once(sub_tf_node, timeout_sec=0.01)
                rclpy.spin_once(sub_imu_node, timeout_sec=0.01)
                rclpy.spin_once(sub_lidar_node, timeout_sec=0.01)
                window.set_motor_ang_vel_label()
                window.update_imu_data()
                window.update_laser_scan_data()
                window.pub_target_vel_msg()

            except KeyboardInterrupt:
                pass

        sub_imu_node.destroy_node()
        sub_tf_node.destroy_node()
        sub_angvel_node.destroy_node()
        sub_lidar_node.destroy_node()
        pub_target_vel_nod.destroy_node()
        rclpy.shutdown()


class update_map_Thread(QThread):
    show_mainbot_odom = pyqtSignal()
    show_laser_scan=pyqtSignal()

    def __init__(self):
        super().__init__()

    def run(self):
        while True:
            if not (window.ui.tab_1.isHidden()):
                window.scene3.clear()
                window.update_mainbot_orientation_log()
                if window.laser_scan_view_flag:
                    self.show_laser_scan.emit()
                self.show_mainbot_odom.emit()

            self.msleep(int(1000 / 20))


class UI(QWidget):
    def __init__(self, parent=None):
        super(UI, self).__init__(parent)
        self.ui = control_ui.Ui_Form()
        self.ui.setupUi(self)
        self.ui.retranslateUi(self)
        self.grayPen = QPen(QColor(211, 211, 211))
        self.grayPen.setWidth(2)
        self.redPen = QPen(QColor(200, 0, 0))
        self.redPen.setWidth(4)
        self.mainbot_imu = Imu()
        self.laser_scan = LaserScan()
        self.laser_scan_view_flag=False
        self.ui.laser_scan_view_btn.clicked.connect(self.set_laser_scan_view_onoff)

        self.Vx_vel = 0.0
        self.Vy_vel = 0.0
        self.W_vel = 0.0
        self.mainbot_x = 0
        self.mainbot_y = 0
        self.mainbot_w = 0
        self.mainbot_pos_x=0
        self.mainbot_pos_y=0

        self.move_update_flag = False
        self.mainbot_moving_log = [[0 for j in range(4)] for i in range(MOVING_LOG_SIZE)]
        self.save_moving_data_size = 0

        self.ui.Vx_doubleSpinBox.valueChanged.connect(self.spin_selected)
        self.ui.Vy_doubleSpinBox.valueChanged.connect(self.spin_selected)
        self.ui.W_doubleSpinBox.valueChanged.connect(self.spin_w_selected)
        self.ui.Vx_horizontalSlider.valueChanged.connect(self.scroll_selected)
        self.ui.Vy_horizontalSlider.valueChanged.connect(self.scroll_selected)
        self.ui.W_horizontalSlider.valueChanged.connect(self.scroll_w_selected)
        self.ui.vel_rst_btn.clicked.connect(self.vel_rst)
        scene1 = QGraphicsScene()
        scene1.addPixmap(QPixmap("images/mecanumbot.png"))
        self.ui.mecanum.setScene(scene1)
        self.ui.mecanum.show()

        self.scene2 = QGraphicsScene()
        self.scene2.addEllipse(2, 2, 150, 150, self.grayPen)
        self.scene2.addEllipse(58, 58, 38, 38, self.grayPen)
        self.scene2.addLine(77, 58, 120, 15, self.grayPen)
        self.scene2.addLine(15, 120, 58, 77, self.grayPen)
        self.scene2.addLine(35, 15, 77, 58, self.grayPen)
        self.scene2.addLine(96, 77, 138, 120, self.grayPen)
        self.scene2.addLine(96, 77, 138, 35, self.grayPen)
        self.scene2.addLine(35, 139, 77, 96, self.grayPen)
        self.scene2.addLine(15, 35, 58, 77, self.grayPen)
        self.scene2.addLine(77, 96, 120, 138, self.grayPen)
        self.clc1 = QGraphicsEllipseItem(75, 75, 4, 4)
        self.clc1.setPen(self.redPen)
        self.scene2.addItem(self.clc1)
        self.set_vel_veiw_scene2()
        self.ui.vel_veiw.setScene(self.scene2)
        self.ui.vel_veiw.show()

        self.scene3 = QGraphicsScene()
        self.map_x_zeropoint = self.ui.map.geometry().width() / 2
        self.map_y_zeropoint = self.ui.map.geometry().height() / 2
        self.ui.map.setScene(self.scene3)
        self.ui.map.show()

        self.T1 = ros_Tread1()
        self.T1.start()

        self.T2 = update_map_Thread()
        self.T2.show_mainbot_odom.connect(self.show_mainbot_odom_on_map)
        self.T2.show_laser_scan.connect(self.show_laser_scan_on_map)
        self.T2.start()


    def set_laser_scan_view_onoff(self):
        if self.laser_scan_view_flag:
            self.laser_scan_view_flag=False
        else :
            self.laser_scan_view_flag=True
    def set_vel_veiw_scene2(self):
        x = (self.Vy_vel * 1000) * 150 / 230 / 2
        y = (self.Vx_vel * 1000) * 150 / 230 / 2
        meg = math.sqrt(x ** 2 + y ** 2)
        if meg > 77:
            x = x * 77 / meg
            y = y * 77 / meg
        self.clc1.setRect(int(75 + x), int(75 - y), 4, 4)

    def set_vel_velue_label(self):
        self.ui.Vx_value.setText('{:.2f}'.format(self.Vx_vel))
        self.ui.Vy_value.setText('{:.2f}'.format(self.Vy_vel))
        self.ui.W_value.setText('{:.2f}'.format(self.W_vel))

    def set_motor_ang_vel_label(self):
        self.ui.FL_angVel.setText('{:.2f}'.format(sub_angvel_node.FL_Motor_Angvel))
        self.ui.FR_angVel.setText('{:.2f}'.format(sub_angvel_node.FR_Motor_Angvel))
        self.ui.BL_angVel.setText('{:.2f}'.format(sub_angvel_node.BL_Motor_Angvel))
        self.ui.BR_angVel.setText('{:.2f}'.format(sub_angvel_node.BR_Motor_Angvel))

    def show_mainbot_odom_on_map(self):
        k = 0
        for i in self.mainbot_moving_log:
            pen = QPen(QColor(200, MOVING_LOG_SIZE - k, MOVING_LOG_SIZE - k))
            pen.setWidth(2)
            self.mainbot_pos_x = self.map_x_zeropoint + i[1]
            self.mainbot_pos_y = self.map_y_zeropoint + i[2]
            x= self.mainbot_pos_x -2
            y= self.mainbot_pos_y -2
            self.scene3.addEllipse(x, y, 5, 5, pen)
            pen.setWidth(1)
            self.scene3.addLine(x + 2, y + 2, x + 2 + math.sin(i[3]) * 8, y + 2 + math.cos(i[3]) * 8, pen)
            k += 1

    def show_laser_scan_on_map(self):
        angle_min=self.laser_scan.angle_min
        angle_increment=self.laser_scan.angle_increment
        k=0
        for i in self.laser_scan.ranges:
            x=self.mainbot_pos_x+math.cos(angle_min+angle_increment*k)*i
            y=self.mainbot_pos_y+math.sin(angle_min+angle_increment*k)*i
            self.scene3.addRect(x-1,y-1,3,3,QPen(QColor(255,255,255)))
            self.scene3.addLine(self.mainbot_pos_x,self.mainbot_pos_y,x,y,QPen(QColor(200,200,200)))
            k+=1


    def update_laser_scan_data(self):
        self.laser_scan = sub_lidar_node.lidar_data

    def update_imu_data(self):
        tempx = self.mainbot_x
        tempy = self.mainbot_y
        tempw = self.mainbot_w
        self.mainbot_imu = sub_imu_node.Imu_data
        self.mainbot_x = int(sub_imu_node.Imu_data.orientation.x * 100) / 5  # cm/ 5pix
        self.mainbot_y = int(sub_imu_node.Imu_data.orientation.y * 100) / 5
        self.mainbot_w = int(sub_imu_node.Imu_data.orientation.w * 100) / 5
        if not (tempx == self.mainbot_x and tempy == self.mainbot_y and tempw == self.mainbot_w):
            self.move_update_flag = True

    def update_mainbot_orientation_log(self):
        time = self.mainbot_imu.header.stamp.sec + self.mainbot_imu.header.stamp.nanosec / 10 ** 9
        x = self.mainbot_imu.orientation.x
        y = self.mainbot_imu.orientation.y
        w = self.mainbot_imu.orientation.w
        if self.move_update_flag:
            if self.save_moving_data_size < MOVING_LOG_SIZE:
                self.mainbot_moving_log[self.save_moving_data_size][0] = time
                self.mainbot_moving_log[self.save_moving_data_size][1] = x
                self.mainbot_moving_log[self.save_moving_data_size][2] = y
                self.mainbot_moving_log[self.save_moving_data_size][3] = w
                self.save_moving_data_size += 1
            else:
                self.mainbot_moving_log.pop(0)
                data = [time, x, y, w]
                self.mainbot_moving_log.append(data)
            self.move_update_flag = False

    def set_vel_velue_spinbox(self):
        self.ui.Vx_doubleSpinBox.setValue(self.Vx_vel)
        self.ui.Vy_doubleSpinBox.setValue(self.Vy_vel)
        self.ui.W_doubleSpinBox.setValue(self.W_vel)

    def set_vel_velue_slider(self):
        self.ui.Vx_horizontalSlider.setValue(int(self.Vx_vel * 100))
        self.ui.Vy_horizontalSlider.setValue(int(self.Vy_vel * 100))
        self.ui.W_horizontalSlider.setValue(int(self.W_vel * 100))

    def pub_target_vel_msg(self):
        pub_target_vel_nod.update_msg(self.Vx_vel, self.Vy_vel, self.W_vel)
        rclpy.spin_once(pub_target_vel_nod)

    def scroll_selected(self):
        self.Vx_vel = self.ui.Vx_horizontalSlider.value() / 100.0
        self.Vy_vel = self.ui.Vy_horizontalSlider.value() / 100.0
        self.W_vel = 0.0
        self.set_vel_velue_label()
        self.set_vel_velue_slider()
        self.set_vel_velue_spinbox()
        self.set_vel_veiw_scene2()

    def scroll_w_selected(self):
        self.Vx_vel = 0.0
        self.Vy_vel = 0.0
        self.W_vel = self.ui.W_horizontalSlider.value() / 100.0
        self.set_vel_velue_label()
        self.set_vel_velue_slider()
        self.set_vel_velue_spinbox()
        self.set_vel_veiw_scene2()

    def spin_w_selected(self):
        self.Vx_vel = 0.0
        self.Vy_vel = 0.0
        self.W_vel = self.ui.W_doubleSpinBox.value()
        self.set_vel_velue_label()
        self.set_vel_velue_slider()
        self.set_vel_velue_spinbox()
        self.set_vel_veiw_scene2()

    def spin_selected(self):
        self.Vx_vel = self.ui.Vx_doubleSpinBox.value()
        self.Vy_vel = self.ui.Vy_doubleSpinBox.value()
        self.W_vel = 0.0
        self.set_vel_velue_label()
        self.set_vel_velue_slider()
        self.set_vel_velue_spinbox()
        self.set_vel_veiw_scene2()

    def vel_rst(self):
        self.Vx_vel = 0.0
        self.Vy_vel = 0.0
        self.W_vel = 0.0
        self.set_vel_velue_label()
        self.ui.Vx_horizontalSlider.setValue(0)
        self.ui.Vy_horizontalSlider.setValue(0)
        self.ui.W_horizontalSlider.setValue(0)
        self.ui.Vx_doubleSpinBox.setValue(0.0)
        self.ui.Vy_doubleSpinBox.setValue(0.0)
        self.ui.W_doubleSpinBox.setValue(0.0)
        self.set_vel_veiw_scene2()


def main(args=None):
    rclpy.init(args=args)
    global pub_target_vel_nod
    global sub_angvel_node
    global window
    global sub_tf_node
    global sub_imu_node
    global sub_lidar_node
    pub_target_vel_nod = pub.pub_target_vel()
    sub_angvel_node = sub.sub_motor_anlvel()
    sub_imu_node = sub.sub_imu_data()
    sub_tf_node = sub.sub_tf_data()
    sub_lidar_node = sub.sub_lidar_data()
    app = QApplication(sys.argv)
    window = UI()
    window.show()

    try:
        sys.exit(app.exec())
    except KeyboardInterrupt:
        pass


if __name__ == '__main__':
    main()

这是我的 git https://github.com/cananella/Ros2-whit-PyQt6-Ui.git

它工作得很好,直到我编写了与激光扫描相关的代码。 直到项目截止日期我都没有时间学习,所以代码看起来就像意大利面条一样。我想知道如何优化代码。

python ros pyqt6
1个回答
0
投票

QThread

  1. 由于 python GIL,简单的任务可能需要更长的时间
  2. 无法处理用户界面
  3. 用于需要长延迟的任务

Q定时器

  1. 长延迟任务会减慢 UI 速度
  2. 用于简单任务
© www.soinside.com 2019 - 2024. All rights reserved.