GPS学习(一):在ROS2中将GPS经纬度数据转换为机器人ENU坐标系,在RVIZ中显示坐标轨迹
文章目录
- 一、GPS模块介绍
- 二、坐标转换
- 转换原理
- 参数解释:
- 增加回调函数
- 效果演示
本文记录在Ubuntu22.04-Humbel中使用NMEA协议GPS模块的过程,使用国产ROS开发板鲁班猫(LubanCat )进行调试。
一、GPS模块介绍
在淘宝找了款性价比较高的轮趣科技GPS北斗双模定位模块作为入门学习使用,支持GNSS系统(北斗、GPS、GLONASS、日本的QZSS以及卫星增强系统SBAS),定位精度在2.5m左右,属于民用级别。引出了常用的几个外部接口,主要用type-c调试比较方便,售后技术也相当给力。接线示意图如下,注意:测试时需要将GPS天线放置在室外,否则模块将没有GPS信号
二、坐标转换
机器人基于Ubuntu-ROS平台做开发调试,所以需要将GPS模块的经纬度和高度信息转化为机器人所能认识的本地坐标系(局部笛卡尔坐标系)。参考其他博主案例,使用半正矢公式来将经纬度转为xyz坐标值。
转换原理
半正矢公式介绍:
半正矢公式是一种根据两点的经度和纬度来确定大圆上两点之间距离的计算方法,在导航有着重要地位。它是球面三角学中“半正矢定理”公式的特例,该定理涉及了球面三角形的边和角。
对于任何球面上的两点,圆心角的半正矢值可以通过如下公式计算:
hav( d r \frac{d}{r} rd)=hav( ψ 2 \psi_{2} ψ2- ψ 1 \psi_{1} ψ1)+cos( ψ 1 \psi_{1} ψ1)cos( ψ 2 \psi_{2} ψ2)hav( λ 2 \lambda_{2} λ2- λ 1 \lambda_{1} λ1)
hav 是半正矢函数的缩写:
haversin( θ \theta θ)= s i n 2 sin^{2} sin2( ( θ ) 2 \frac{(\theta)}{2} 2(θ))= 1 − c o s ( θ ) 2 \frac{1-cos(\theta)}{2} 21−cos(θ)
参数解释:
d :两点之间的距离(沿大圆,见球面距离);
r :球的半径;
ψ 1 \psi_{1} ψ1 ψ 2 \psi_{2} ψ2 :点 1 的纬度和点 2 的纬度,以弧度制度量;
λ 1 \lambda_{1} λ1 λ 2 \lambda_{2} λ2:点 1 的经度和点 2 的经度,以弧度制度量。
等号左边的 d r \frac{d}{r} rd:圆心角,单位是弧度。
所以,可以通过应用反半正矢函数(如果可以查到值)或通过使用反正弦函数来解出d :
d = r ∗ a r c h a v ( h ) d=\sqrt[]{r*archav(h)} d=r∗archav(h) = 2r*arcsin h \sqrt[]{h} h)
将h=hav d r \frac{d}{r} rd代入后可得:
对于中短距离来说,半正矢公式是计算地球表面 GPS 坐标之间距离的有用且相对准确的方法,在距离较长时其准确性可能会降低。
增加回调函数
这里简单解释一下gpsCallback回调函数的内容,此处订阅sensor_msgs::msg::NavSatFix数据格式的GPS话题进行数据处理。
//将纬度和经度值从度数转换为弧度。
double rad(double d)
{return d * 3.1415926 / 180.0;
}
void gps_callback(const sensor_msgs::msg::NavSatFix::SharedPtr gps_msg)
{if (!pose_init){// Initialization code remains the same.//使用接收到的 GPS 消息中的纬度、经度和高度false进行初始化,只初始化一次init_pose.latitude = gps_msg->latitude;init_pose.longitude = gps_msg->longitude;init_pose.altitude = gps_msg->altitude;init = true;}else{//计算当前 GPS 位置与初始 GPS 位置之间的纬度和经度变化double radLat1 ,radLat2, radLong1,radLong2,delta_lat,delta_long,x,y;double deltaLat_y ,deltaLong_x;deltaLat_x = 0; deltaLong_y = 0;radLat1 = rad(init_pose.latitude);//初始化位置的纬度radLong1 = rad(init_pose.longitude);//初始化位置的经度radLat2 = rad(gps_msg->latitude);//当前位置的纬度radLong2 = rad(gps_msg->longitude);//当前位置的经度deltaLat = radLat2 - radLat1; deltaLong = radLong2 - radLong1;// 代入公式进行计算x的坐标值x = 2 * asin(sqrt(pow(sin(delta_lat / 2), 2) + cos(radLat1) * cos(radLat2) * pow(sin(deltaLong_y / 2), 2));//公式计算结果默认为弧度,所以这里要转换成m的单位x = x * EARTH_RADIUS * 1000; // 代入公式进行计算y的坐标值y = 2 * asin(sqrt(pow(sin(deltaLat_x / 2), 2) + cos(radLat2) * cos(radLat2) * pow(sin(deltaLong / 2), 2));y = y * EARTH_RADIUS * 1000; // Convert to meters.// 将高度差计算为z的坐标值double z = gps_msg->altitude - init_pose.altitude;//将计算得到的xyz值发布为ROS中的PoseStamped数据,作为路径发布ros_path_.header.frame_id = "path";ros_path_.header.stamp = rclcpp::Node::now();geometry_msgs::msg::PoseStamped pose;pose.header = ros_path_.header;pose.pose.position.x = x;pose.pose.position.y = y;pose.pose.position.z = z;ros_path_.poses.push_back(pose);state_pub_.publish(ros_path_);}
}
效果演示
使用nmea_navsat_driver驱动启动GPS模块,源码链接:https://github.com/ros-drivers/nmea_navsat_driver/tree/ros2
ros2 launch nmea_navsat_driver nmea_serial_driver.launch.py
然后启动坐标转换节点,将经纬度数据从WGS-84 坐标转换到机器人真实世
界 xyz 坐标系下(一般为东北天方向),以第一个经纬度数据为原点,不断描绘实时经纬度数据的位移方向,显示为机器人运行轨迹图。
ros2 launch gps_path gps_path.launch.py
打开rviz2,修改 Fixed Frame 为path,电机左下角[add],根据topic添加[gps_path]->path后,显示效果为:
相关文章:

GPS学习(一):在ROS2中将GPS经纬度数据转换为机器人ENU坐标系,在RVIZ中显示坐标轨迹
文章目录 一、GPS模块介绍二、坐标转换转换原理参数解释: 增加回调函数效果演示 本文记录在Ubuntu22.04-Humbel中使用NMEA协议GPS模块的过程,使用国产ROS开发板鲁班猫(LubanCat )进行调试。 一、GPS模块介绍 在淘宝找了款性价比较高的轮趣科技GPS北斗双…...

chatgpt生成文本的底层工作原理是什么?
文章目录 🌟 ChatGPT生成文本的底层工作原理🍊 一、数据预处理🍊 二、模型结构🍊 三、模型训练🍊 四、文本生成🍊 总结 📕我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN…...

javaEE -11(10000字HTML入门级教程)
一: HTML HTML 代码是由 “标签” 构成的. 例如: <body>hello</body>标签名 (body) 放到 < > 中大部分标签成对出现. 为开始标签, 为结束标签.少数标签只有开始标签, 称为 “单标签”.开始标签和结束标签之间, 写的是标签的内容. (h…...
LeetCode75——Day21
文章目录 一、题目二、题解 一、题目 1207. Unique Number of Occurrences Given an array of integers arr, return true if the number of occurrences of each value in the array is unique or false otherwise. Example 1: Input: arr [1,2,2,1,1,3] Output: true Ex…...

学习笔记---更进一步的双向链表专题~~
目录 1. 双向链表的结构🦊 2. 实现双向链表🐝 2.1 要实现的目标🎯 2.2 创建初始化🦋 2.2.1 List.h 2.2.2 List.c 2.2.3 test.c 2.2.4 代码测试运行 2.3 尾插打印头插🪼 思路分析 2.3.1 List.h 2.3.2 List.…...
vscode格式化代码, 谷歌风格, 允许短if同行短块同行, tab = 4舒适风格
ctrl ,输入format, 点开C风格设置 在这块内容输入{ BasedOnStyle: Chromium, IndentWidth: 4, ColumnLimit: 200, AllowShortIfStatementsOnASingleLine: true, AllowShortLoopsOnASingleLine: true} C_Cpp: Clang_format_fallback Style 用作回退的预定义样式的名称&#x…...

百度富文本上传图片后样式崩塌
🔥博客主页: 破浪前进 🔖系列专栏: Vue、React、PHP ❤️感谢大家点赞👍收藏⭐评论✍️ 问题描述:上传图片后,图片会变得很大,当点击的时候更是会顶开整个的容器的高跟宽 原因&#…...
autoware.ai中检测模块lidar_detector caffe
lidar_apollo_cnn_seg_detect模块:该模块主要是调用百度apollo的目标分割。 1.需要安装caffe进行实现: caffe安装步骤: git clone https://github.com/BVLC/caffecd caffe && mdkir build && cd buildcmake ..出现报错: CM…...
CentOS安装Ruby环境
安装依赖项 sudo yum install -y perl zlib-devel openssl-devel安装git sudo yum install -y git git config --global http.sslVerify falsecurl取消ssl认证 echo "insecure" >> ~/.curlrc安装rbenv https://github.com/rbenv/rbenv git clone https://…...
力扣第509题 斐波那契数 新手动态规划(推荐参考) c++
题目 509. 斐波那契数 简单 相关标签 递归 记忆化搜索 数学 动态规划 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0&a…...

canvas绘制签名并保存
实现签名的三个关键方法: 1.mousedown:当鼠标按下时开始绘制签名。 2.mousemove:鼠标移动时持续绘制。 3.mouseup:鼠标抬起时结束绘制。 html: <div class"setSign"><canvasref"canvas&q…...

Android渲染流程
目录 缓冲区的不同生命周期代表当前缓冲区的状态: 多个源 ViewRootImpl: Android4.0: Android5.0: Android应用程序调用SurfaceFliger将测量,布局,绘制好的Surface借助GPU渲染显示到屏幕上。 一个Acti…...
牛客-【237题】算法基础精选题单-第二章 递归、分治
第二章 递归、分治 递归NC15173 The Biggest Water ProblemNC22164 更相减损术 递归 NC15173 The Biggest Water Problem 简单递归,直接暴力 #include <math.h> #include <stdio.h> #include <algorithm> #include <cstring> #include &…...

leetcode-字符串
1.反转字符串LeetCode344. 20230911 难度为0,此处就不放代码了 注意reverse和swap等一系列字符串函数什么时候该用,记一记库函数 swap可以有两种实现,涨知识了,除了temp存值还可以通过位运算:s[i] ^ s[j]; s[j] ^ s[i…...

多线程---synchronized特性+原理
文章目录 synchronized特性synchronized原理锁升级/锁膨胀锁消除锁粗化 synchronized特性 互斥 当某个线程执行到某个对象的synchronized中时,其他线程如果也执行到同一个对象的synchronized就会阻塞等待。 进入synchronized修饰的代码块相当于加锁 退出synchronize…...

Qt实现卡牌对对碰游戏
效果 闲来无事,实现一个对对碰游戏,卡牌样式是火影动漫。 先上效果: 卡牌对对碰_火影主题 玩法 启动游戏,进入第一关卡,所有卡牌都为未翻开状态,即背面朝上;点击卡牌,则将卡牌翻开…...

【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割7(数据预处理)
在上一节:【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割6(数据预处理) 中,我们已经得到了与mhd图像同seriesUID名称的mask nrrd数据文件了,可以说是一一对应了。 并且,mask的文件,还根据结…...

极米科技H6 Pro 4K、H6 4K高亮定焦版——开启家用投影4K普及时代
智能投影产业经过几年发展,市场规模正在快速扩大。洛图数据显示,预计今年中国投影出货量有望超700万台,2027年达950万台,可见智能投影产业规模将逐渐壮大,未来可期。2023年,投影行业呈现出全新面貌…...

软考系统架构师知识点集锦九:数据库系统
一、考情分析 二、考点精讲 2.1数据库概述 2.1.1数据库模式 (1)三级模式:外模式对应视图,模式(也称为概念模式)对应数据库表,内模式对应物理文件。(2)两层映像:外模式-模式映像,模式-内模式映像;两层映像可以保证数据库中的数据具有较高的…...

IOC课程整理-6 Spring IoC 依赖注入
1 依赖注入的模式和类型 模式 类型 2 自动绑定(Autowiring) 官方定义 “自动装配是Spring框架中一种机制,用于自动解析和满足bean之间的依赖关系。通过自动装配,Spring容器可以根据类型、名称或其他属性来自动连接协作的bean&…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...