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

文章目录

  • 介绍
  • 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_noneserial_.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 headeruint32 seqtime stampstring frame_id
geometry_msgs/Quaternion orientationfloat64 xfloat64 yfloat64 zfloat64 w
float64[9] orientation_covariance
geometry_msgs/Vector3 angular_velocityfloat64 xfloat64 yfloat64 z
float64[9] angular_velocity_covariance
geometry_msgs/Vector3 linear_accelerationfloat64 xfloat64 yfloat64 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.mzph.cn/news/57859.shtml

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

相关文章

Java抽象类——抽象类与普通类的区别

abstract抽象类 1、含义&#xff1a;类和类之间具有共同特征&#xff0c;将这些共同特征提取出来&#xff0c;就形成抽象类。。。 在 java 中&#xff0c;被 abstract 关键字修饰的类叫做抽象类&#xff0c;被abstract关键字修饰的方法叫做抽象方法。 抽象类本身是不存在的&…

量化面试-概率题

文章目录 一、题目1.糖果罐&#xff08;绿皮书79页&#xff09;2 折木棍&#xff08;绿皮书89页&#xff09;3 第一张ACE&#xff08;绿皮书95页&#xff09;4 n个均匀分布之和&#xff08;绿皮书95页&#xff09; 二、答案1. 糖果罐2 折木棍3 第一张ACE4 n个均匀分布之和 一、…

spring事件和线程池区别

Spring事件&#xff08;Spring Event&#xff09;和线程池&#xff08;Thread Pool&#xff09;是两个不同的概念。 Spring事件是Spring框架中的一种机制&#xff0c;用于在应用程序中实现发布-订阅模式。通过定义事件和监听器&#xff0c;可以在特定事件发生时&#xff0c;通…

pytest笔记: pytest单元测试框架

第一步&#xff1a;安装 和查看版本 pycharm settings 查看 第二步&#xff1a; 编写test_example.py def inc(x):return x1 def test_answer():assert inc(4) 5 第三步&#xff1a;在当前路径下执行pytest 命令 PS E:\data\web测试\Selenium3自动化测试实战——基于Pyth…

专题:曲面的切平面、法线

假设曲面方程为隐函数 F ( x , y , z ) 0 &#xff0c;点 M ( x 0 , y 0 , z 0 ) 是其上一点 又在点 M 处任意引一条在曲面上的曲线&#xff0c;设该曲线参数方程为&#xff1a; { x φ ( t ) y ψ ( t ) z ω ( t ) &#xff0c;且当 t t 0 时&#xff0c; x x 0 , y y…

Flink流批一体计算(18):PyFlink DataStream API之计算和Sink

目录 1. 在上节数据流上执行转换操作&#xff0c;或者使用 sink 将数据写入外部系统。 2. File Sink File Sink Format Types Row-encoded Formats Bulk-encoded Formats 桶分配 滚动策略 3. 如何输出结果 Print 集合数据到客户端&#xff0c;execute_and_collect…

鼎盛合方案——充气泵的原理和结构

充气泵是一种常见的气体压缩设备&#xff0c;它可以将空气或其他气体压缩成高压气体&#xff0c;用于充气、输送、压缩等工业和生活领域。充气泵的原理是利用机械或电动力量将气体压缩&#xff0c;使其体积减小&#xff0c;压力增大&#xff0c;从而达到充气的目的。 充气泵的…

力扣:74. 搜索二维矩阵(Python3)

题目&#xff1a; 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非递减顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返…

解决Linux报错:Swap file “xxxxxx.swp“ already exists

出现问题 Swap file “.models_conf.yaml.swp” already exists! 在 Linux 下 vim 编辑过程中&#xff0c;由于某种原因异常退出正在编辑的文件&#xff0c;再次编辑该文件时&#xff0c;会出现如下提示&#xff1a; 一个文件出现了带有.swp的副本文件的时候&#xff0c;会出现…

MySQL概述,架构原理

一.MySQL简介 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典的MySQL AB公司开发&#xff0c;后被oracle公司收购&#xff0c;MySQL是当下最流行的关系型数据库管理系统之一&#xff0c;在WEB应用方面&#xff0c;MySQL是最好的RDBMS&#xff08;Relational Database Man…

Mybatis小记

目录 Mybatis第一个程序 xml文件 测试类 错误排查 Mybatis第一个程序 1.搭建实验数据库 2.导入MyBatis相关jar包 3.编写MyBatis核心配置文件 4.编写MyBatis工具类 5.创建实体类、 6.编写Mapper接口类 7.编写Mapper.xml配置文件 8.编写测试类 对象传参只引用需要的属性就可…

【设计模式】Head First 设计模式——装饰者模式 C++实现

设计模式最大的作用就是在变化和稳定中间寻找隔离点&#xff0c;然后分离它们&#xff0c;从而管理变化。将变化像小兔子一样关到笼子里&#xff0c;让它在笼子里随便跳&#xff0c;而不至于跳出来把你整个房间给污染掉。 设计思想 动态地将责任附加到对象上&#xff0c;若要扩…

新生代与老年代

在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;内存被划分为多个不同的区域&#xff0c;其中包括新生代&#xff08;Young Generation&#xff09;和老年代&#xff08;Old Generation&#xff09;。 新生代是用于存储新创建的对象的区域。大多数对象在创建后很快就变…

springboot RabbitMQ客户端连接故障恢复

最近做RabbitMQ故障演练发现RabbitMQ服务器停止后&#xff0c;基于springboot的消费端不可以自动的恢复&#xff0c;队列的消费者消失&#xff0c;消息一直积压到队列中&#xff0c;这种情况肯定是不可接收的&#xff1b;通过研究源代码找到了解决方案。 一、添加自动恢复配置a…

基于AVR128单片机抢答器proteus仿真设计

一、系统方案 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 void timer0_init() //定时器初始化 { TCCR00x07; //普通模式&#xff0c;OC0不输出&#xff0c;1024分频 TCNT0f_count; //初值&#xff0c;定时为10ms TIFR0x01; //清中断标志…

Oracle-day3:子查询、with as语句、聚合函数

一、单行子查询 /*一、单行子查询格式&#xff1a;select <列明表> from 表名(查询select 语句)where 列或表达式 比较运算符(SELECT 列名 FROM 表名 WHERE 条件)-- 子查询&#xff0c;必须要使用小括号括起来---最大值函数&#xff1a;max()最小值函数: min()二、 from…

ChatGPT Prompting开发实战(二)

一、基于LangChain源码react来解析prompt engineering 在LangChain源码中一个特别重要的部分就是react&#xff0c;它的基本概念是&#xff0c;LLM在推理时会产生很多中间步骤而不是直接产生结果&#xff0c;这些中间步骤可以被用来与外界进行交互&#xff0c;然后产生new con…

Oracle ASM (Automatic Storage Management)

[TOC](Oracle ASM (Automatic Storage Management)) Oracle ASM (Automatic Storage Management) 是 Oracle 的一个磁盘管理和文件系统服务&#xff0c;用于简化数据库文件的分布。 在使用 ASM 管理磁盘时&#xff0c;如果想要增加存储空间&#xff0c;您可以向现有的磁盘组添加…

IdentityServer密码长度超长会导致跳转到登录页

应用系统项目的安全要求越来越高&#xff0c;基本都是采取https等加密证书传输&#xff0c;无法使用https的&#xff0c;也是要求不能明文传输内容&#xff0c;因此做一些等保要求&#xff0c;密码需要加密后才能传输给服务端&#xff0c;所以前端会采取一些密码手段&#xff0…

block层:7. 请求下发

blk_dispatch 源码基于5.10 1. blk_mq_sched_dispatch_requests void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx) {// 队列struct request_queue *q hctx->queue;// 队列已停止或者被暂停if (unlikely(blk_mq_hctx_stopped(hctx) || blk_queue_quiesc…