zoukankan      html  css  js  c++  java
  • [开源项目] 蓝点无限 UWB Python版本上位机

    初衷:           
               进一步降低学习门槛,使用纯Python 编写GUI 上位机,Python 易于编程,算法资料算法丰富。  
              TWR 算法上位机一般使用Deca官方提供的GUI上位机,使用QT C++编写,代码臃肿,不适合学习,同时三边定位算法部分晦涩难懂。
              之前在论坛开源了底层固件,再次补充一个开源版本上位机,实现了全流程的开源。

    界面预览:


    源码文件:
    1.twr_51uwb_v2.py  主函数入口,同时处理TCP连接和界面显示
    2.twr_main.py 主要负责数据结构解析,并实现定位计算,这个文件有三边定位算法,大家可以替换尝试其他算法
    3.Coordinate_process.py 基站坐标处理,匹配预设基站地址,确定基站坐标
    4. globalvar.py 共享全局变量,主要多文件共享基站地址和坐标信息
    5.mainwindow.py 界面文件,使用qtdesign 绘制,并使用pyuic 自动生成的文件

    主要功能:
    1 通过TCP 获取信息,串口转TCP参见视频https://www.bilibili.com/video/BV1rv411p7Hj/
    2 解析收到的数据并完成解算
    3 在界面显示基站和标签相对位置
    4 统计框中显示标签坐标
    5 上位机支持多基站,并且可以根据checkbox 确认是否使能基站
    6 支持调试接口,可以将想要的数据打印到调试界面
    7 支持标签history 定位点数量设定,默认5,最大20
    8 支持标签根据历史信息显示不同透明度

    开发环境:
    Python 3.6(64bit),推荐集成开发环境PyCharm 社区版
    主要库:pyqt5,numpy

    其他:
    目前找的三边算法,只支持2D 定位,并且需要4个基站。大家可以根据需要替换定位算法。

    tril2d = Trilateration()
    tril2d.setDistances(Info['distance'])
    tril2d.setAnthorCoor(Info['anthor'])
    result_x, result_y = tril2d.trilaterate2D()

    数据格式说明:
    &&&:20$0005:AD$0001:0080:11#0002:0080:22#0003:0081:33#0004:0079:44$AA##
    TODO

    源码:

    论坛开源链接下载:http://51uwb.cn/forum.php?mod=viewthread&tid=401&extra=page%3D1

    改上位机可以匹配我们全新开源固件,可以应用与隧道等复杂定位场景。目前可以使用已有代码简单修改为4基站,若干标签定位。 多基站+若干标签定位全新固件已经开发完成,链接  http://51uwb.cn/forum.php?mod=viewthread&tid=402&extra=page%3D1     




    同时该上位机支持现有BP30/BP400固件,只需要定位固件代码修改3个地方:
    1 修改最大基站数目

    #define MAX_ANTHOR 4

    2 修改tx_main.c 数据格式 

    点击查看代码
    static void Send_Dis_To_Anthor0(void)
        {
                 // printf("Debug here");
            static int framenum = 0 ;
                        char crc_byte = 0;
            //only send this message to anthor0:short address equal 0x0001
            msg_f_send.destAddr[0] =(0x0001) &0xFF;
            msg_f_send.destAddr[1] =  ((0x0001)>>8) &0xFF;
    
            msg_f_send.seqNum = distance_seqnum;
    
            msg_f_send.messageData[0]='M';
                        uint8 *pAnthor_Str = &msg_f_send.messageData[1];
                        int str_len = 0x20;
                  sprintf(pAnthor_Str, "&&&:%02X$%04X:%02X",str_len,SHORT_ADDR,msg_f_send.seqNum);//AA55 ANTHORID
            pAnthor_Str = pAnthor_Str + 15;
                  //printf(pAnthor_Str);
                 //0001:A1B1:11#
                  uint16 shortaddress = 0x0001;
                  uint8 rssi = 0x11;
                  sprintf(pAnthor_Str, "%04X:%04X:%02X#",shortaddress,Final_Distance[0],rssi);
            pAnthor_Str = pAnthor_Str + 13;
    
                        shortaddress = 0x0002;
                  rssi = 0x22;
                  sprintf(pAnthor_Str, "%04X:%04X:%02X#",shortaddress,Final_Distance[1],rssi);
            pAnthor_Str = pAnthor_Str + 13;
    
                        shortaddress = 0x0003;
                  rssi = 0x33;
                  sprintf(pAnthor_Str, "%04X:%04X:%02X#",shortaddress,Final_Distance[2],rssi);
            pAnthor_Str = pAnthor_Str + 13;
    
                        shortaddress = 0x0004;
                  rssi = 0x44;
                  sprintf(pAnthor_Str, "%04X:%04X:%02X$AA##",shortaddress,Final_Distance[3],rssi);
            pAnthor_Str = pAnthor_Str + 17;
    
                  sprintf(pAnthor_Str, "
    ");
                       
                        while(msg_f_send.messageData[str_len] != '
    ')
                        {
                                crc_byte =crc_byte^msg_f_send.messageData[str_len];
                                str_len++;
                        }
            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, !GPIO_PIN_RESET);//PA node ,enable pa
            dwt_writetxdata(11 + str_len,(uint8 *)&msg_f_send, 0) ;  // write the frame data
            dwt_writetxfctrl(11 + str_len, 0);
            dwt_starttx(DWT_START_TX_IMMEDIATE);
            while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))
            { };
                        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);
            framenum++;
            LCD_Display_Distance();
        }

    3 修改rx_main.c 上传数据量

    case 'M':
             USART_puts(&msg_f->messageData[1],72);
        break;

    说明:
    按照如上修改固件,分别编译标签和4个基站,将定位距离数据通过地址为0x0001 的基站串口输出,并通过串口转WIFI模块传入到上位机。

    整体TODO
    上位机:     上位机动态选取最优4个基站定位(RSSI最大)
    固件增强:  固件目前没有提取RSSI,固定使用4基站,后期可以改成动态,通过动态发现周围基站并测距,然后汇总。

      

    博客讨论一些室内定位(DWM1000/CC2431/CC2530) 以及一些随性的技术。博文可以转载,但需要注明出处!
  • 相关阅读:
    一个貌似比较吊的递归转换为loop--总算成功了.
    为何反转迭代顺序就不会栈溢出了?
    将树形递归转换为loop
    递归和迭代之间的转换简单例子
    非线性递归函数转化为迭代函数举例
    将尾递归函数转换为迭代函数的利器
    转:LINUX/UNIX下的回车换行与WINDOWS下的区别
    property干嘛的
    eval和列表解析的一处陷阱
    剑指offer——16二进制中1的个数
  • 原文地址:https://www.cnblogs.com/tuzhuke/p/15170193.html
Copyright © 2011-2022 走看看