Eine Methode zur Ermittlung der tatsächlichen Position eines Mehrlinienradars

Da es mühsam ist, den manuellen Bandtest in rviz zu bestehen, habe ich mir eine andere Lösung überlegt. (Ich bin ein Neuling. Wenn etwas nicht stimmt, nehmen Sie es einfach zum Spaß)

Es kann auch als Aufzeichnung des Wachstumsprozesses angesehen werden. Der Code lautet wie folgt:

# -*- coding:utf8 -*-

import json
import pickle
from PyQt5 import QtGui
from threading import Thread  # 导入线程模块
from multiprocessing import Process
from PyQt5.QtCore import pyqtSignal, QStringListModel, Qt
from PyQt5.QtWidgets import QMainWindow, QApplication, QTableWidgetItem, QMessageBox, QDialog, QTabWidget, \
    QTabBar  # PYQT5

from window import Ui_MainWindow  # 导入自己的ui窗体
from Get_coordinate_data import Ros_Get_Data  # 导入Ros.py
from new_child import Ui_Dialog

import math
import socket
import os
import sys

class Ui_Window(QMainWindow):
    """
        UI窗口类
    """
    Get_data = pyqtSignal(list)  # 自定义信号,用作接收和发送坐标信息

    def __init__(self):
        QMainWindow.__init__(self)

        self.main_ui = Ui_MainWindow()  # 给主窗口定义一个对象
        self.main_ui.setupUi(self)

        self.main_next = Setps_Next_Ui()

        self.deal_with = 0

        self.send_data_list = []  # 信号发送的列表容器
        self.need_data = 0  # 将需要的数据条数初始化
        self.item_distance_list = []  # 为存放距离的列表




        self.nearly_item_distance_deal_with = []  # 为存放近距离计算结果的列表

        self.perimeter_item_distance_deal_with = []  # 为存放中距离计算结果的列表

        self.far_item_distance_deal_with = []  # 为存放远距离计算结果的列表






        self.index_a = 0  # 索引值变量 对应数据坐标中的x
        self.index_b = 1  # 索引值变量 对应数据坐标中的y
        self.index_c = 2  # 索引值变量 对应数据坐标中的角度
        self.col = 0  # 写入ui窗体表格的列

        self.Get_Text_data()  # 获取需求文件中的数据
        self.ProcDataSocketServer()  # 调用函数

        self.register()  # 定义按钮

        os.system("gnome-terminal -e 'roscore'")  # 通过新终端打开roscore

        self.op_thread = Thread(target=self.open_rviz)  # 开启进程,打开rviz
        self.op_thread.start()
    def register(self):
        """
            使按钮连接各自的对象
        """
        self.main_ui.start.clicked.connect(self.main_next.show)
        self.main_ui.close.clicked.connect(self.close_Laser)
        self.main_ui.start.clicked.connect(self.main_ui.tableWidget.clearContents)
        self.main_ui.start.clicked.connect(self.start_thread)  # 将开始按钮连接到start_thread方法函数


        self.Get_data.connect(self.collect_data)  # 将自定义信号Get_data连接到collect_data函数

    def close_Laser(self):
        pass

    def Get_Text_data(self):
        filename = "configuration_file.json"  # 获取../fc_file文件里的数据
        with open(filename, "r") as f:  # 获取../fc_file文件里的数据
            self.target_text_all = json.load(f)
            self.target_distance = self.target_text_all["Laser_radar"][0]["distance"]  # 使target_distance得到json文件中距离要求的值
            self.differential = self.target_text_all["Laser_radar"][1]["differential"]

    def start_thread(self):
        """
            开启线程
        """

        text = ["程序已启动,请前往rviz中确认点云中的边角距离。"]  # 将提示信息写入到文本框里
        output_message = QStringListModel()
        output_message.setStringList(text)
        self.main_ui.listView.setModel(output_message)

        self.deal_with = 0

        self.flag = True

        self.index_a = 0
        self.index_b = 1  # 每当点击一次线程时 初始化索引值
        self.index_c = 2  # 每当点击一次线程时 初始化索引值
        self.need_data = 0  # 初始化ros里的循环值
        self.col = 0  # 列
        self.send_data_list = []  # 信号发送的列表容器
        self.item_distance_list = []  # 初始化距离写入列表

        self.nearly_item_distance_deal_with = []  # 初始化近距离计算数据列表
        self.perimeter_item_distance_deal_with = []  # 初始化距离计算数据列表
        self.far_item_distance_deal_with = []  # 初始化距离计算数据列表

        self.main_ui.start.setEnabled(False)  # 将开始按钮设定为不可点击
        self.thread_server = Thread(target=self.run)  # 为ui_ros.Get_data_work开启线程
        self.thread_server.daemon = True  # 线程保护
        self.thread_server.start()  # 开始
        p = Process(target=Process_clienct)  # 开启进程
        p.start()

    def open_rviz(self):
        import os
        os.system('rviz -d rviz_configuration_file.rviz')

    def collect_data(self, data):
        """
            由 start_thread 开启的函数方法,为了写入ui窗体表格
        """
        self.send_data_list.append(data[self.index_a])  # 将坐标数据里的对应值放入到send_data_list里
        self.send_data_list.append(data[self.index_b])
        self.send_data_list.append(data[self.index_c])

        self.deal_with += 1
        if self.deal_with % 2 == 0:
            self.item_distance_list = math.sqrt(
                (self.send_data_list[-6] - self.send_data_list[-3]) ** 2 +
                (self.send_data_list[-5] - self.send_data_list[-2]) ** 2)  # 将边长参数计算出来
            if self.need_data <= 12:
                self.nearly_item_distance_deal_with.append(self.item_distance_list)  # 为计算边长列表添加计算的数据
            elif self.need_data <= 24:
                self.perimeter_item_distance_deal_with.append(self.item_distance_list)
            elif self.need_data <= 36:
                self.far_item_distance_deal_with.append(self.item_distance_list)
        self.input_table()

        self.need_data += 1
        if self.need_data == 12:
            nearly_item = "近距离测试结束,请将目标板放置于中距离,放置完成后继续点击。"
            QMessageBox.information(self, '测试结束', nearly_item, QMessageBox.Ok)
        if self.need_data == 24:
            perimeter_item = "中距离测试结束,请将目标板放置于远距离,放置完成后继续点击。"
            QMessageBox.information(self, '测试结束', perimeter_item, QMessageBox.Ok)
        if self.need_data == 36:
            self.main_ui.start.setEnabled(True)  # 将开始按钮设定为可点击

            text = ["数据采集完成"]  # 数据采集结束后 会将数据采集完成输出到文本提示框上
            output_message = QStringListModel()
            output_message.setStringList(text)
            self.main_ui.listView.setModel(output_message)

            self.result_ui()  # 调用计算数据的函数

    def input_table(self):

        newItem_x = str(self.send_data_list[self.index_a])
        x = QTableWidgetItem(newItem_x)  # 转换成窗体格式
        self.main_ui.tableWidget.setItem(0, self.col, x)  # 将数据写入ui窗体表格里
        self.col += 1

        newItem_y = str(self.send_data_list[self.index_b])  # 把列表强制转换成字符串
        y = QTableWidgetItem(newItem_y)  # 转换成窗体格式
        self.main_ui.tableWidget.setItem(0, self.col, y)  # 将数据写入ui窗体表格里
        self.col += 1

        newItem_z = str(self.send_data_list[self.index_c])
        z = QTableWidgetItem(newItem_z)
        self.main_ui.tableWidget.setItem(0, self.col, z)  # 将数据写入ui窗体表格里
        self.col += 1

        if self.deal_with % 2 == 0:
            self.item_distance_list = '%.4f' % self.item_distance_list  # 将位置数据保留4位小数
            newItem_distance = str(self.item_distance_list)  # 将距离数据转换成字符串格式
            item_distance = QTableWidgetItem(newItem_distance)  # 转换成窗体格式
            self.main_ui.tableWidget.setItem(0, self.col, item_distance)  # 将数据写入ui窗体表格里
            self.col += 1

        self.index_a += 3
        self.index_b += 3
        self.index_c += 3

    def result_ui(self):
        """
            计算数据的函数
        """
        nearly_item_distance_deal_with_ok = sum(self.nearly_item_distance_deal_with) / len(self.nearly_item_distance_deal_with)  #
        perimeter_item_distance_deal_with_ok = sum(self.perimeter_item_distance_deal_with) / len(self.perimeter_item_distance_deal_with)  #
        far_item_distance_deal_with_ok = sum(self.far_item_distance_deal_with) / len(self.far_item_distance_deal_with)  #

        nearly_item_distance_deal_with_ok = float('%.4f' % nearly_item_distance_deal_with_ok)
        perimeter_item_distance_deal_with_ok = float('%.4f' % perimeter_item_distance_deal_with_ok)
        far_item_distance_deal_with_ok = float('%.4f' % far_item_distance_deal_with_ok)

        self.input_data(nearly_item_distance_deal_with_ok,
                        perimeter_item_distance_deal_with_ok,far_item_distance_deal_with_ok)  # 将计算完成的数据放到input_data函数里

    def input_data(self, nearly_item_distance_deal_with_ok,
                        perimeter_item_distance_deal_with_ok,far_item_distance_deal_with_ok):
        """
            将result_ui的数据写入到文本框里
        :param text:result_ui的数据
        """
        nearly_differential = abs(nearly_item_distance_deal_with_ok-self.target_distance)
        perimeter_differential = abs(perimeter_item_distance_deal_with_ok-self.target_distance)
        far_differential = abs(far_item_distance_deal_with_ok-self.target_distance)

        unqualified_output_data = "近距离边长的平均值:{}m\n中距离边长的平均值:{}m\n远距离边长的平均值:{}m\n实际的边长是:{}m\n" \
                                  "近距离误差:{}m\n中距离误差:{}m\n远距离误差:{}m\n要求是:{}m\n标定的结果为:不合格".format(
            nearly_item_distance_deal_with_ok, perimeter_item_distance_deal_with_ok,far_item_distance_deal_with_ok,
            self.target_distance,nearly_differential,perimeter_differential,far_differential,self.differential
        )
        qualified_output_data = "近距离边长的平均值:{}m\n中距离边长的平均值:{}m\n远距离边长的平均值:{}m\n实际的边长是:{}m\n" \
                                "近距离误差:{}m\n中距离误差:{}m\n远距离误差:{}m\n要求是:{}m\n标定的结果为:合格".format(
            nearly_item_distance_deal_with_ok,perimeter_item_distance_deal_with_ok,far_item_distance_deal_with_ok,
            self.target_distance,nearly_differential,perimeter_differential,far_differential,self.differential
        )

        if nearly_differential < self.differential and \
                perimeter_differential < self.differential and \
                far_differential < self.differential:  # 将数据和要求作比较
            QMessageBox.information(self, '测试结束', qualified_output_data, QMessageBox.Ok)  # 全部符合条件

        else:
            QMessageBox.information(self, '测试结束', unqualified_output_data, QMessageBox.Ok)  # 如果距离不合格

    def closeEvent(self, QCloseEvent):
        self.sock.close()
        self.flag = False
        print "程序运行结束"

    def ProcDataSocketServer(self):
        self.sock = socket.socket(socket.AF_UNIX)
        SOCK_PATH = "/tmp/testss"  # 统一本地文件地址为"/tmp/testss"

        try:
            os.unlink(SOCK_PATH)
        except:
            pass
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(SOCK_PATH)  # 连接到本地文件
        self.sock.listen(5)  # 最大监听数量为5
        os.chmod(SOCK_PATH, 0777)

    def run(self):
        conn, addr = self.sock.accept()
        while self.flag:
            data = conn.recv(1024)  # 数据接收一次最大为1024
            try:
                order = pickle.loads(data)  # 进行解包
                if order is None:  # 如果数据为空
                    conn.close()  # 断开连接
                    continue
                else:
                    if "type" in order:
                        if order["type"] == "data":
                            order = order["data"]
                            print order
                            self.Get_data.emit(order)
                            ret = 1
                            conn.send(str.encode(str(ret)))
                        elif order["type"] == "wait":
                            ret = 0
                            conn.send(str.encode(str(ret)))
                        else:
                            print "server is close"
            except:
                break
        conn.close()

class Process_clienct():
    def __init__(self):
        self.ui_ros = Ros_Get_Data()
        self.ui_ros.connectAndSendData()  # 执行Ros_Get_Uwb里的connectAndSendData

class Setps_Next_Ui(QDialog):
    def __init__(self):
        QDialog.__init__(self)

        self.setWindowFlags(Qt.WindowCloseButtonHint)  # 隐藏关闭按钮
        self.text_ui = Ui_Dialog()  # 给主窗口定义一个对象
        self.text_ui.setupUi(self)

        # 隐藏标签
        self.text_ui.tabWidget.tabBar().hide()
        self.text_ui.tabWidget.findChildren(QTabBar)[0].hide()

        self.register()

    def register(self):  # 按钮连接
        self.text_ui.next_page_one.clicked.connect(self.widget_index_one)
        self.text_ui.next_page_two.clicked.connect(self.widget_index_two)
        self.text_ui.privious_page.clicked.connect(self.widget_index_three)

        self.text_ui.picture_point.clicked.connect(self.rviz_point)

        self.text_ui.index_6_return.clicked.connect(self.widget_return_3)

    def widget_index_one(self):
        self.text_ui.tabWidget.setCurrentIndex(1)

    def widget_index_two(self):
        self.text_ui.tabWidget.setCurrentIndex(2)

    def widget_index_three(self):
        self.text_ui.tabWidget.setCurrentIndex(1)

    def rviz_point(self):
        self.text_ui.tabWidget.setCurrentIndex(3)
        png3 = QtGui.QPixmap('./picture/edges.png')
        self.text_ui.picture_text.setPixmap(png3)
        self.text_ui.picture_text.setScaledContents(True)

    def widget_return_2(self):
        self.text_ui.tabWidget.setCurrentIndex(1)

    def widget_return_3(self):
        self.text_ui.tabWidget.setCurrentIndex(2)

    def closeEvent(self, QCloseEvent):
        pass


if __name__ == '__main__':
    """
        运行入口
    """
    app = QApplication(sys.argv)  # 创建应用
    window = Ui_Window()  # 给主窗口定义对象
    window.show()  # 展示主界面
    sys.exit(app.exec_())

Siehe den folgenden Link auf der Ros-Seite

https://blog.csdn.net/weixin_54062353/article/details/124292981

Das UI-Formular sieht wie folgt aus

https://blog.csdn.net/weixin_54062353/article/details/124293590

Supongo que te gusta

Origin blog.csdn.net/weixin_54062353/article/details/124292864
Recomendado
Clasificación