保姆级教程之UWB传感器室内高精度定位位置数据移植进ROS2

使用的uwb型号为Decawave(已被QORVO公司收购)产的DWM1001C(Nordic Semiconductor  nRF52832  SoC),其扩展组件为MDEK1001。其使用官方提供的安卓APP:Decawave DRTLS Manager应用进行定位。且此APP我已在此文章资源中提交,可以进行下载。

1.简单介绍UWB超宽带定位技术

        UWB技术是一种使用1GHz以上频率带宽的无线载波通信技术。UWB技术具有系统复杂度低,发射信号功率谱密度低,对信道衰落不敏感,截获能力低,定位精度高等优点尤其适用于室内等密集多径场所的高速无线接入。

2.使用官方映像刷新DWM1001

( 若你的UWB固件一直闪烁红灯,则代表固件无法正常工作。若你的固件在闪烁红灯同时其他颜色的灯也在闪烁,则代表正常工作可跳过此步骤。)

1.下载板载包,官方烧录软件等

        板载包:DWM1001附带预刷写的固件出厂映像。此映像在DWM1001板载包中提供。可从官网资料进行下载:DWM1001C - Qorvohttps://www.qorvo.com/products/p/DWM1001C

        烧录软件:https://www.segger.com/downloads/https://www.youtube.com/redirect?event=video_description&redir_token=QUFFLUhqa2dzV3lRazdWOE9CWnVvSHpFdHhEZzNRX2hVZ3xBQ3Jtc0trcXpkeHc2N1FhNjVCTi0tRGc5d3RieTBHZmFKelE4Sm9lSEU0RDZxczA2NzVpWjNaVFJXRWE1YzItbXJ5YW9rUi1DZUVSY25maFZUeGxXZVI2d29yRnRoMGF3ZVRobnZ5WHNWd3FlQm5iR1ZyX3U4TQ&q=https://www.segger.com/downloads/embedded-studio&v=emjC0HYd5gE找到Embedded Studio 与J-Link并下载并选择适配你电脑的版本(大多数均为windows  64位),下载后开始进行安装。(进行安装步骤时尽量按照系统选定的默认安装路径不要更改)

下载成功后,会出现三个APP:SEGGER Embedded Studio 8.22(SES)J-Flash V8.12J-Link Commander V8.12。

2.擦除以及烧录等

        参考以下两篇博客:

J-Flash工具的使用---擦除、烧录及校验-CSDN博客

J-link J-flash 工程配置及下载_jflash软件安装包下载-CSDN博客

注:在J-flash创建新的文件后,选择版型型号位:Nordic  Semiconductor  nRF52832_xxAA

且打开的文件为前面官网下载板载包中的DWM1001_PANS_R2.0.hex

3.利用官方提供的DRTLS 安卓APP进行四基站(anchor)一标签(tag)的组网

APP以及官方APP指导手册我已放在文章资源里,可参考。注意:这里四个基站独立供电,一个标签放置在无人车上并通过串口连接主控。

官方YouTube视频教程:

https://www.youtube.com/watch?v=XJ9W7B2eZFw&t=24s

组网完成后效果如下:

点开Grid可看见栅格地图以及基站,标签的实时位置。至此组网完成。

4.通过串口使用DWM1001固件的内置 Shell 命令行模式(CLI)读取tag数据位置数据

        

讲解一下何为CLI以及如何理解:

        DWM1001 的内置 Shell 命令行模式(CLI,Command Line Interface 即命令行接口),可以直接与模块交互,发送命令、获取位置信息、配置参数等。这是 DWM1001 自带的固件(RTLS,Real Time Location System)的一部分。

        

        CLI:Command Line Interface 的缩写,它是一种通过命令行文字交互的方式,和计算机程序沟通的界面。

        

        这是在 Linux 终端中,通过串口连接访问 DWM1001 模块固件的命令行。模块内运行的是 Decawave 官方烧录的固件,并不是你自己编写的程序。

        

        这个 CLI 是直接由 DWM1001 内部 MCU 处理的,和 ROS 等系统没有直接关系,所以需要写代码自动读取这些数据发布到ROS中。

1.将UWB固件连接主控识别串口号与完成串口别名

        因为我们要知道连接主控的这个UWB标签固件的串口号是哪一个才好进行串口通信,串口别名是为了固定串口名,防止下次上电串口名被Linux随机分配,同时也方便我们通过别名快速区分不同的UWB固件

识别与别名请参考我的这一篇博客:

十分钟教会你Ubantu下串口识别与串口别名-CSDN博客

2.安装minicom(用以串口通信):

sudo apt install minicom 

3.通过minicom与串口/dev/ttyACM0通信,这里以/dev/ttyACM0举个例子。

sudo minicom -D /dev/ttyACM0

进入后会显示Welcome字样,之后一直按住Enter键,会出现@字样,一直到有dwm>提示符字样出现才代表成功。

4.进入dwm>提示符后查看内置命令菜单

        输入,即可看到内置Shell 命令菜单        

** Command group: Base **
?: this help                                                                    
help: this help                                                                 
quit: quit                                                                      
                                                                                
** Command group: GPIO **                                                       
gc: GPIO clear                                                                  
gg: GPIO get                                                                    
gs: GPIO set                                                                    
gt: GPIO toggle                                                                 
                                                                                
** Command group: SYS **                                                        
f: Show free memory on the heap                                                 
reset: Reboot the system                                                        
si: System info                                                                 
ut: Show device uptime                                                          
frst: Factory reset                                                             
                                                                                
** Command group: SENS **                                                       
twi: General purpose TWI read                                                   
aid: Read ACC device ID                                                         
av: Read ACC values                                                             
scs: Stationary config set                                                      
scg: Stationary config get                                                      
                                                                                
** Command group: LE **                                                         
les: Show meas. and pos.                                                        
lec: Show meas. and pos. in CSV                                                 
lep: Show pos. in CSV                                                           
                                                                                
** Command group: UWB **                                                        
utpg: Get TxPwr                                                                 
utps: Set TxPwr                                                                 
                                                                                
** Command group: UWBMAC **                                                     
nmg: Get node mode                                                              
nmp: Set UWB mode to passive                                                    
nmo: Set UWB mode to off                                                        
nma: Set mode to AN                                                             
nmi: Set mode to ANI                                                            
nmt: Set mode to TN                                                             
nmtl: Set mode to TN-LP                                                         
nmb: Set mode to BN                                                             
la: Show AN list                                                                
lb: Show BN list                                                                
nis: Set Network ID                                                             
nls: Set node label                                                             
udi: Show incoming IoT data                                                     
uui: Send IoT data                                                              
stg: Get stats                                                                  
stc: Clear stats                                                                
                                                                                
** Command group: API **                                                        
tlv: Send TLV frame                                                             
aurs: Set upd rate                                                              
aurg: Get upd rate                                                              
apg: Get pos                                                                    
aps: Set pos                                                                    
acas: Set anchor config                                                         
acts: Set tag config                                                            
aks: Set encryption key                                                         
akc: Clear encryption key                                                       
ans: Set NVM usr data                                                           
anc: Clear NVM usr data                                                         
ang: Get NVM usr data                                                           
                                                                                
** Tips **                                                                      
Press Enter to repeat the last command            

5.让这个UWB模块汇报当前自己坐标

在进入dwm提示符后,输入 lep (location engine position)并按回车。

可以看见POS信息不停的在输出

其POS格式为POS,x,y,z,quality

x, y, z:表示标签当前相对于原点的位置(单位:米)

quality:定位质量指标(通常范围是 0~100,值越高代表定位越可靠)

5. 创建c++节点,实时读取串口数据并发送到ROS2话题中

使用 C++ 节点,读取Tag标签串口 /dev/ttyACM0 数据。

只发布以 POS, 开头的数据行。

发布消息类型为 std_msgs::msg::String 到 ROS2 话题   /dwm1001/tag_pos。

工作空间为  uwbpos_ws。

1.准备 ROS2 工作空间 uwbpos_ws (每一行分开进行)

mkdir -p ~/uwbpos_ws/src

cd ~/uwbpos_ws

colcon build

source install/setup.bash

2.创建功能包 dwm1001_serial_pub

cd ~/uwbpos_ws/src
ros2 pkg create --build-type ament_cmake dwm1001_serial_pub --dependencies rclcpp std_msgs

3.编写 C++ 节点代码

在src/dwm1001_serial_pub/src/下创建dwm_pub.cpp文件并编辑

touch dwm_pub.cpp


gedit dwm_pub.cpp

dwm_pub.cpp节点完整代码如下:

#include <rclcpp/rclcpp.hpp>
#include <std_msgs/msg/string.hpp>
#include <fstream>
#include <string>
#include <sstream>

class DWMSerialNode : public rclcpp::Node
{
public:
    DWMSerialNode() : Node("dwm_serial_node")
    {
        publisher_ = this->create_publisher<std_msgs::msg::String>("/dwm1001/tag_pos", 10);

        // 打开串口
        serial_.open("/dev/ttyACM0", std::ios::in);
        if (!serial_.is_open()) {
            RCLCPP_ERROR(this->get_logger(), "无法打开串口 /dev/ttyACM0");
            rclcpp::shutdown();
            return;
        }

        // 创建定时器,周期读取串口数据
        timer_ = this->create_wall_timer(
            std::chrono::milliseconds(50),
            std::bind(&DWMSerialNode::read_serial, this)
        );

        RCLCPP_INFO(this->get_logger(), "DWM1001串口节点启动,监听 /dev/ttyACM0...");
    }

private:
    void read_serial()
    {
        std::string line;
        if (std::getline(serial_, line)) {
            // 去除回车换行符
            line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
            line.erase(std::remove(line.begin(), line.end(), '\n'), line.end());

            if (line.rfind("POS,", 0) == 0) {
                auto msg = std_msgs::msg::String();
                msg.data = line;
                publisher_->publish(msg);
                RCLCPP_INFO(this->get_logger(), "发布: %s", line.c_str());
            }
        }
    }

    std::ifstream serial_;
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
    rclcpp::TimerBase::SharedPtr timer_;
};

int main(int argc, char *argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<DWMSerialNode>());
    rclcpp::shutdown();
    return 0;
}

Cmakelists.txt完整内容:

cmake_minimum_required(VERSION 3.8)
project(dwm1001_serial_pub)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)

# 添加可执行文件
add_executable(dwm_pub src/dwm_pub.cpp)
ament_target_dependencies(dwm_pub rclcpp std_msgs)

# 安装目标
install(TARGETS
  dwm_pub
  DESTINATION lib/${PROJECT_NAME}
)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  set(ament_cmake_cpplint_FOUND TRUE)
  set(ament_cmake_copyright_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

4.构建包: 

cd ~/uwbpos_ws


colcon build


source install/setup.bash

5.在工作空间内运行节点:

ros2 run dwm1001_serial_pub dwm_pub

至此tag标签位置已成功移植到ROS2中 

若出现串口占用导致Device or resource busy,参考我的这篇博客:

解决串口占用导致Device or resource busy问题-CSDN博客

6.多Tag模式下的UWB的listen(监听)模式设置以及相关说明:

此为附加内容,即你的项目中需要不止一个tag,需要监听并发布所有tag坐标。新增了一个连接小车的固件作为监听者,且串口号为/dev/ttyACM1。listen是用来监听整个DRTLS系统中所有的tag位置坐标的

由前面的命令菜单可知

在dwm>提示符后输入nmp ,即进入Passive 模式。

Passive Mode,用于监听其他 Tag 的位置信息,自己则不发出信息,只监听

在dwm>提示符后输入si,查看此固件具体详细信息

例如输出:dwm> si
[000033.920 INF] sys: fw2 fw_ver=x01030001 cfg_ver=x00010700
[000033.920 INF] uwb0: panid=x87AE addr=xDECA787B04402B8A    #网络 ID 和该模块的唯一地址
[000033.930 INF] mode: tn (pasv,twr,np,le)  #表示当前 Tag 处于 Passive 模式,并开启了 定位引擎(le)
[000033.930 INF] uwbmac: connected  #已成功连接到网络(即已加入你之前搭建的 anchor 网络)
[000033.930 INF] uwbmac: bh disconnected
[000033.940 INF] cfg: sync=0 fwup=0 ble=1 leds=1 le=1 lp=0 stat_det=1 (sens=1) mode=0 upd_rate_norm=1 upd_rate_stat=1 label=DW2B8A
[000033.950 INF] enc: off
[000033.950 INF] ble: addr=F1:A1:D9:1C:E7:41

 在dwm>提示符后输入les后,这将显示 所有可见 Tag 的位置 (我的两个tag名字为512F,C985)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值