在ros中利用串口serial发布fdilink的gps话题

news2025/1/16 16:49:21

文章目录

  • 介绍
  • FDILink通讯协议
    • 数据帧组成
    • 数据包
  • 数据处理
    • 打开串口
    • 在头文件中定义参数
    • 串口读取
  • 代码运用
    • 依赖:
    • 使用:
  • 源码

介绍

DETA100系列 是一个提供 GNSS/INS & AHRS 系统的模组,在最苛刻的条件下提供准确的位置、速度、加速度和姿态数据。它结合了温度校准的加速度计,陀螺仪,磁力计与一个双天线RTK、GNSS接收器。这些是耦合在一个复杂的融合算法,以提供准确和可靠的导航和方向。同时DETA100系列 支持辅助设备的数据接入,如里程计、光流计、RTCM 数据等。

FDILink通讯协议

数据帧组成

在这里插入图片描述
A: 指令类别
在这里插入图片描述
B:载荷的字节数。
C:流水号, 每发送一个数据帧数值加一,用于检测数据帧丢包。
D:帧头CRC8校验,计算帧头部分 起始标志 + 指令类别 + 数据长度 + 流水序号。
E:数据CRC16校验,计算载荷数据的CRC16校验。

数据包

以双天线为例
在这里插入图片描述
在这里插入图片描述

数据处理

打开串口

  try
  {
    serial_.setPort(serial_port_);
    serial_.setBaudrate(serial_baud_);
    serial_.setFlowcontrol(serial::flowcontrol_none);
    serial_.setParity(serial::parity_none); //default is parity_none
    serial_.setStopbits(serial::stopbits_one);
    serial_.setBytesize(serial::eightbits);
    serial::Timeout time_out = serial::Timeout::simpleTimeout(serial_timeout_);
    serial_.setTimeout(time_out);
    serial_.open();
  }
  catch (serial::IOException &e)
  {
    ROS_ERROR_STREAM("Unable to open port ");
    exit(0);
  }

在头文件中定义参数

进行指令和字节数赋值
以双天线消息为例

#define TYPE_GNSS 0x78 //指令ID
#define GNSS_DUAL_ANTENNA_DATA_LEN 0x86  //字节数长度 134 = 133+1

定义双天线消息的数据结构

#pragma pack(1)
struct Gnss_Dual_Antenna_data_Packet_t
{
	uint32_t Microseconds;
	double RoverRtkRefPosN;
	double RoverRtkRefPosE;
	double RoverRtkRefPosD;
	double MBRtkRefPosN;
	double MBRtkRefPosE;
	double MBRtkRefPosD;
	double RoverLat;
	double RoverLon;
	float RoverAlt;
	float Rover_hAcc;
	float Rover_vAcc;
	double MBLat;
	double MBLon;
	float MBAlt;
	float MBhAcc;
	float MBvAcc;
	double RoverRtkPosLength;
	float RoverRtkAccuracyLength;
	double RoverRtkPosHeading;
    float RoverRtkAccuracyHeading;
	uint8_t MBfixtype;
	uint8_t Roverfixtype;    
};
#pragma pack()

串口读取

    else if (head_type[0] == TYPE_GNSS)
    {
      Gnss_Dual_Antenna_data_frame_.frame.header.header_start   = check_head[0];
      Gnss_Dual_Antenna_data_frame_.frame.header.data_type      = head_type[0];
      Gnss_Dual_Antenna_data_frame_.frame.header.data_size      = check_len[0];
      Gnss_Dual_Antenna_data_frame_.frame.header.serial_num     = check_sn[0];
      Gnss_Dual_Antenna_data_frame_.frame.header.header_crc8    = head_crc8[0];
      Gnss_Dual_Antenna_data_frame_.frame.header.header_crc16_h = head_crc16_H[0];
      Gnss_Dual_Antenna_data_frame_.frame.header.header_crc16_l = head_crc16_L[0];
      uint8_t CRC8 = CRC8_Table(Gnss_Dual_Antenna_data_frame_.read_buf.frame_header, 4);
      if (CRC8 != Gnss_Dual_Antenna_data_frame_.frame.header.header_crc8)
      {
        ROS_WARN("header_crc8 error");
        continue;
      }
      if(!frist_sn_){
        read_sn_  = Gnss_Dual_Antenna_data_frame_.frame.header.serial_num - 1;
        frist_sn_ = true;
      }
 else if (head_type[0] == TYPE_GNSS)
    {
      uint16_t head_crc16_l = Gnss_Dual_Antenna_data_frame_.frame.header.header_crc16_l;
      uint16_t head_crc16_h = Gnss_Dual_Antenna_data_frame_.frame.header.header_crc16_h;
      uint16_t head_crc16 = head_crc16_l + (head_crc16_h << 8);
      size_t data_s = serial_.read(Gnss_Dual_Antenna_data_frame_.read_buf.read_msg, (GNSS_DUAL_ANTENNA_DATA_LEN + 1)); //134+1
      // if (if_debug_){
        // for (size_t i = 0; i < (GNSS_DUAL_ANTENNA_DATA_LEN + 1); i++)
        // {
        //   std::cout << std::hex << (int)Gnss_Dual_Antenna_data_frame_.read_buf.read_msg[i] << " ";
        // }
        // std::cout << std::dec << std::endl;
        // std::cout << "frame_end: " << std::hex << (int)Gnss_Dual_Antenna_data_frame_.frame.frame_end<< std::dec << std::endl;
      // }
      uint16_t CRC16 = CRC16_Table(Gnss_Dual_Antenna_data_frame_.frame.data.data_buff, GNSS_DUAL_ANTENNA_DATA_LEN);
      if (if_debug_){          
        std::cout << "CRC16:        " << std::hex << (int)CRC16 << std::dec << std::endl;
        std::cout << "head_crc16:   " << std::hex << (int)head_crc16 << std::dec << std::endl;
        std::cout << "head_crc16_h: " << std::hex << (int)head_crc16_h << std::dec << std::endl;
        std::cout << "head_crc16_l: " << std::hex << (int)head_crc16_l << std::dec << std::endl;
        bool if_right = ((int)head_crc16 == (int)CRC16);
        std::cout << "if_right: " << if_right << std::endl;
      }
      
      if (head_crc16 != CRC16)
      {
        ROS_WARN("check crc16 faild(gnss).");
        continue;
      }
      else if(Gnss_Dual_Antenna_data_frame_.frame.frame_end != FRAME_END)
      {
        ROS_WARN("check frame end.gnss");
        continue;
      }
    }

代码运用

依赖:

sudo apt install ros-melodic-serial

使用:

ahrs_driver.launch

<launch>
  <node pkg="fdilink_ahrs" name="ahrs_driver" type="ahrs_driver" output="screen" >
    <!-- 是否输出debug信息 -->
    <param name="debug"  value="false"/>
    
    <!-- 串口设备,可通过rules.d配置固定 -->
    <param name="port"  value="/dev/ttyUSB0"/>
    <!-- <param name="port"  value="/dev/ttyTHS1"/> -->

    <!-- 波特率 -->
    <param name="baud"  value="921600"/>

    <!-- 发布的imu话题名 -->
    <param name="imu_topic"  value="/imu"/>
    
    <!-- 发布的imu话题中的frame_id -->
    <param name="imu_frame"  value="imu"/>

    <!-- 地磁北的yaw角 --> # 二维指北的朝向,北为0,逆时针增加,0~2π的取值范围。
    <param name="mag_pose_2d_topic"  value="/mag_pose_2d"/>

    <!-- 发布的数据基于不同设备有不同的坐标系   -->
    <param name="device_type"  value="1"/> <!-- 0: origin_data, 1: for single imu or ucar in ROS, 2:for Xiao in ROS -->
  </node>
</launch> 

其中device_type

  1. Deta-10的原始坐标系模式
  2. 单独imu的坐标系模式

调用的ahrs_driver节点会发布sensor_msgs/Imu格式的imu topic。

std_msgs/Header header
  uint32 seq
  time stamp
  string frame_id
geometry_msgs/Quaternion orientation
  float64 x
  float64 y
  float64 z
  float64 w
float64[9] orientation_covariance
geometry_msgs/Vector3 angular_velocity
  float64 x
  float64 y
  float64 z
float64[9] angular_velocity_covariance
geometry_msgs/Vector3 linear_acceleration
  float64 x
  float64 y
  float64 z
float64[9] linear_acceleration_covariance

也会发布geometry_msgs/Pose2D格式的二维指北角话题,话题名默认为/mag_pose_2d

float64 x
float64 y
float64 theta  # 指北角

源码

链接:https://pan.baidu.com/s/1xG-Hmpuv_GSkeDP47lfApA
提取码:armd

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/944334.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

国标GB28181安防监控视频平台EasyGBS新功能:批量绑定角色与取消设备

国标GB28181协议视频平台EasyGBS是基于国标GB28181协议的视频云服务平台&#xff0c;支持多路设备同时接入&#xff0c;并对多平台、多终端分发出RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。国标视频监控平台可提供视频监控直播、云端录像、云存储、检索回放、智能告警、语音…

多线程(额外扩展)(面试会用)

1 线程状态 1.1 状态介绍 当线程被创建并启动以后&#xff0c;它既不是一启动就进入了执行状态&#xff0c;也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢&#xff1f;Java中的线程 状态被定义在了java.lang.Thread.State枚…

中央发文:提高青年人才资助比例, 放宽学历、年龄限制 (附2023国自然资助比例统计)~

8 月 27 日&#xff0c;中共中央办公厅、国务院办公厅印发《关于进一步加强青年科技人才培养和使用的若干措施》&#xff08;以下简称《若干措施》&#xff09;&#xff0c;明确提出包括提高国家自然科学基金对青年科技人才的资助比例&#xff0c;放宽学历、年龄限制等措施&…

五、多表查询-4.5子查询-表子查询

一、概述 子查询返回的结果是多行多列&#xff0c;这种子查询称为表子查询。 常用的操作符&#xff1a;in 经常出现在from之后 二、演示 【例1】查询与“鹿掌客”、“宋院桥”的职位和薪资相同的员工信息 1、查询与“鹿掌客”、“宋院桥”的职位和薪资 返回的结果是一个表…

请问现在开融资融券账户交易佣金利率最低是多少?怎么开户!

请问现在开融资融券账户交易佣金利率最低是多少&#xff1f;怎么开户&#xff01; 融资融资利率没有最低的说法&#xff0c;利率一般都是相对的&#xff0c;融资融券的利率通常约为6%以上&#xff0c;当然这个也会根据市场货币的政策有所变动&#xff0c;比如现在的的货币政策…

极智嘉(Geek+)再获重磅荣誉,持续力领跑智慧物流行业发展

近日&#xff0c;全球仓储机器人引领者极智嘉(Geek)再度传来好消息&#xff0c;凭借着全球化的专业服务能力和稳健增长的亮眼海外成绩&#xff0c;一举荣登“2023出海品牌服务商”价值榜&#xff0c;成为唯一登榜的物流机器人企业。 作为率先出海的物流机器人企业&#xff0c…

如何在VR头显端实现低延迟的RTSP或RTMP播放

技术背景 VR&#xff08;虚拟现实技术&#xff09;给我们带来身临其境的视觉体验&#xff0c;广泛的应用于城市规划、教育培训、工业仿真、房地产、水利电力、室内设计、文旅、军事等众多领域&#xff0c;常用的行业比如&#xff1a; 教育行业&#xff1a;VR头显可以用于教育…

成都瀚网科技:抖店怎么上精选联盟?

在抖音电商平台上&#xff0c;选定的联盟是一个非常重要的入口。对于商家来说&#xff0c;能够进入选定的联盟意味着更多的曝光度和流量&#xff0c;从而获得更好的销售机会。那么&#xff0c;抖店是如何进入精选联盟的呢&#xff1f; 1、抖店如何加入特色联盟&#xff1f; 提供…

arm版Linux下安装es集群

背景&#xff1a;由于生产上网络没通&#xff0c;没办法&#xff0c;只能自己安装一个es集群的测试环境了&#xff0c;我的电脑是Mac M2&#xff0c;安装的Linux是centos7&#xff0c;也是arm版的。 第一步&#xff1a;查看自己Linux系统的版本 命令&#xff1a;uname -a 例如…

用Kubernetes(k8s)的ingress部署https应用

用Kubernetes的ingress部署https应用 环境准备Ingress安装域名证书准备 部署应用通过ingress暴露应用根据ssl证书生成对应的secret创建ingress暴露部署的应用确认自己安装了ingress创建ingress 访问你暴露的应用 环境准备 Ingress安装 我之前有一片文章写的是用ingress暴露应…

揭秘:企业在线帮助中心的一些技巧秘密!

企业在线帮助中心是现代企业为了提供更好的客户服务而建立的一个重要渠道。它可以帮助客户解决问题、获取产品信息和技术支持。在这篇文章中&#xff0c;我将揭秘一些企业在线帮助中心的技巧秘密&#xff0c;希望能够帮助企业提供更好的客户服务。 一、清晰的导航结构 一个清…

js删除字符串中的指定字符串

1. 使用 replace() 方法 replace() 将字符串中的指定子字符串替换为新的字符串。 如果删除指定的子字符串&#xff0c;可以将它替换为空字符串。 var str "Hello, World!";var substringToRemove "World";var newStr str.replace(substringToRemove, &q…

太阳能景观凉亭

丰富的太阳辐射能是重要的能源&#xff0c;是取之不尽、用之不竭的、无污染、廉价、人类能够自由利用的能源。太阳能每秒钟到达地面的能量高达80万千瓦&#xff0c;假如把地球表面0.1%的太阳能转为电能&#xff0c;转变率5%&#xff0c;每年发电量可达5.61012千瓦小时&#xff…

Oatpp编译使用Windows版本----windows搭建http服务器

来源&#xff1a;微信公众号「编程学习基地」 文章目录 一、Oatpp 编译下载源码cmake构建工程Configue配置x64Generate构建项目 VS2019编译项目 二、Oatpp搭建http服务器VS2019创建空项目导入oatpp项目配置 一、Oatpp 编译 下载源码 下载源码&#xff1a;https://github.com…

装备一台ubuntu

问题&#xff1a;linux在执行ifconfig时出现 Command ‘ifconfig‘ not found ,but can be installed with: 这种情况解决方案&#xff08;参考&#xff09; 描述&#xff1a; 1、安装好linux后想查一下ip地址&#xff0c;一查出现了这种情况 2、执行了这个命令&#xff0c;出…

如何使用CSS实现一个带有动画效果的进度条?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ HTML 结构&#xff1a;⭐ CSS 样式&#xff1a;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那…

Android开发基础之服务Service

尽可能简单理解Android开发四大组件中的服务Service&#xff0c;用简单的例子和语言。 概念 长期在后台运行&#xff0c;与用户没有交互&#xff0c;比如音乐&#xff0c;可以在后台播放&#xff0c;同时可以去看书&#xff0c;浏览新闻等 配置 由于Service也是四大组件之…

2.2 概念模型

思维导图&#xff1a; 学习目标&#xff1a; 学习数据库的概念模型涉及对抽象思维和具体实践的结合。我会采取以下策略来有效学习&#xff1a; 1. **基础理论学习**&#xff1a; - 阅读经典教材和参考书籍&#xff0c;理解关键概念如实体、属性、关系等。 - 观看在线课…

SV-6002Y 网络对讲求助模块,带3W功放输出和一路30W功放输出

SV-6002Y 网络对讲求助模块&#xff0c;带3W功放输出和一路30W功放输出 SV-6002Y是我司一款求助对讲模块&#xff0c;具有10/100M以太网接口&#xff0c;其接收网络的音频数据&#xff0c;实时解码播放&#xff0c;还可配置麦克风输入和扬声器输出。SV-6002Y可实现对讲、广播、…

【爬虫】5.5 Selenium 爬取Ajax网页数据

目录 AJAX 简介 任务目标 创建Ajax网站 创建服务器程序 编写爬虫程序 AJAX 简介 AJAX&#xff08;Asynchronous JavaScript And XML&#xff0c;异步 JavaScript 及 XML&#xff09; Asynchronous 一种创建交互式、快速动态网页应用的网页开发技术通过在后台与服务器进行…