PIXHAWK(ardupilot4.52)NMEA的解析bug

最近在测试过程中发现在椭球高为负的地方,地面站读取GPS_RAW_INT (24)消息中的alt高度竟然是正值。而消息中定义的alt并不是一个unsigned数据,理论上是带有正负符号的。

查看gga的原始信息:

$GPGGA,063718.40,3714.8533856,N,11845.9411766,E,4,35,0.5,-0.3237,M,0.000,M,1.4,0002*60

 高程为-0.3237,高程确实为负值。

修改了一下代码,单独输出一下高程进行测。

//AP_GPS.cpp
void AP_GPS::send_mavlink_gps_raw(mavlink_channel_t chan)
{const Location &loc = location(0);float hacc = 0.0f;float vacc = 0.0f;float sacc = 0.0f;float undulation = 0.0;int32_t height_elipsoid_mm = 0;if (get_undulation(0, undulation)) {height_elipsoid_mm = loc.alt*10 - undulation*1000;}horizontal_accuracy(0, hacc);vertical_accuracy(0, vacc);speed_accuracy(0, sacc);gcs().send_text(MAV_SEVERITY_CRITICAL, "remaining=%ld!",loc.alt * 10UL); //单独输出高程mavlink_msg_gps_raw_int_send(chan,last_fix_time_ms(0)*(uint64_t)1000,status(0),          //解状态loc.lat,        // in 1E7 degreesloc.lng,        // in 1E7 degreesloc.alt * 10UL, // in mmget_hdop(0),get_vdop(0),ground_speed(0)*100,  // cm/sground_course(0)*100, // 1/100 degrees,num_sats(0), //搜星数量height_elipsoid_mm,   // Ellipsoid height in mmhacc * 1000,          // one-sigma standard deviation in mmvacc * 1000,          // one-sigma standard deviation in mmsacc * 1000,          // one-sigma standard deviation in mm/s0,                    // TODO one-sigma heading accuracy standard deviationgps_yaw_cdeg(0));
}

更新固件后,将gga输入,输出确实变成了正值的:320。

继续索源,直接到NMEA解析中查看。

//AP_GPS_NMEA.cpp// Processes a just-completed term
// Returns true if new sentence has just passed checksum test and is validated
bool AP_GPS_NMEA::_term_complete()
{// handle the last term in a message/**省略****/
/**省略****/
/**省略****/case _GPS_SENTENCE_GGA + 9: // Altitude (GPGGA)_new_altitude = _parse_decimal_100(_term); //这里将负值改成正值了!//   _new_altitude = _parse_decimal_100("-1.24"); //这里将负值改成正值了!//   gcs().send_text(MAV_SEVERITY_CRITICAL, "now=%s",_term);//    gcs().send_text(MAV_SEVERITY_CRITICAL, "now=%ld",_new_altitude);break;// course and speed//case _GPS_SENTENCE_RMC + 7: // Speed (GPRMC)case _GPS_SENTENCE_VTG + 5: // Speed (VTG)
/**省略****/
}

请注意这个函数!!

 _new_altitude = _parse_decimal_100(_term); //这里将负值改成正值了!

经过测试,当_parse_decimal_100函数输入"-0.3237",输出是:320。

但是!当输入是"-1.24"时,输出是:-124。

测试结果确实是能区分正负符号的,但是为啥输入-0.3237时,输出是正值呢?

继续看_parse_decimal_100(_term)函数。

//AP_GPS_NMEA.cpp
int32_t AP_GPS_NMEA::_parse_decimal_100(const char *p)
{char *endptr = nullptr;long ret = 100 * strtol(p, &endptr, 10);  //提取到小数点之前的数字int sign = ret < 0 ? -1 : 1;//    gcs().send_text(MAV_SEVERITY_CRITICAL, "ret1=%ld",ret);if (ret >= (long)INT32_MAX) {return INT32_MAX;}if (ret <= (long)INT32_MIN) {return INT32_MIN;}if (endptr == nullptr || *endptr != '.') {return ret;}if (isdigit(endptr[1])) {  //提取小数点后的数字ret += sign * 10 * DIGIT_TO_VAL(endptr[1]);if (isdigit(endptr[2])) {ret += sign * DIGIT_TO_VAL(endptr[2]);if (isdigit(endptr[3])) {ret += sign * (DIGIT_TO_VAL(endptr[3]) >= 5);}}}//   gcs().send_text(MAV_SEVERITY_CRITICAL, "ret2=%ld",ret);return ret;
}

将该函数单独拎出来进行测试,输入-0.3237的结果为:

 输入-1.3237的结果为:

 

问题出现在前端,前端用到了strtol函数 ,strtol函数是将字符串转成长整数,是能够区分正负符号的,但仅提取小数点之前的数值。

那么问题就来了,当小数点之前的数值为0时,0是不分正负的!

所以就导致了输入-0.3237,输出变成了正值的32。

在代码中可以看到有定义一个sign变量进行正负判断,那么现在多加一层判断弥补当小数点之前为0的情况。

//AP_GPS_NMEA.cpp
int32_t AP_GPS_NMEA::_parse_decimal_100(const char *p)
{char *endptr = nullptr;long ret = 100 * strtol(p, &endptr, 10);  //提取到小数点之前的数字int sign = ret < 0 ? -1 : 1;if(ret==0) //优化当数值为-0.1的情况{if(atof(p)<-0.00001)sign=-1;}//    gcs().send_text(MAV_SEVERITY_CRITICAL, "ret1=%ld",ret);if (ret >= (long)INT32_MAX) {return INT32_MAX;}if (ret <= (long)INT32_MIN) {return INT32_MIN;}if (endptr == nullptr || *endptr != '.') {return ret;}if (isdigit(endptr[1])) {  //提取小数点后的数字ret += sign * 10 * DIGIT_TO_VAL(endptr[1]);if (isdigit(endptr[2])) {ret += sign * DIGIT_TO_VAL(endptr[2]);if (isdigit(endptr[3])) {ret += sign * (DIGIT_TO_VAL(endptr[3]) >= 5);}}}//   gcs().send_text(MAV_SEVERITY_CRITICAL, "ret2=%ld",ret);return ret;
}

 再次测试,输入-0.3237时,能够正常输出 -32了

问题解决。 

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

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

相关文章

Linux容器讲解以及对应软件使用

一、容器基础知识讲解 1.1 微服务的部署策略 部署单体应用意味着运行大型应用的多个相同副本&#xff0c;通常提供若干台&#xff08;N&#xff09;服务器&#xff08;物理机或虚拟 机&#xff09;&#xff0c;在每台服务器上运行若干个&#xff08;M&#xff09;应用实例。部…

企业级应用技术-ELK日志分析系统

目录 #1.1ELK平台介绍 1.1.1ELK概述 1.1.2Elasticsearch 1.1.3Logstash 1.1.4Kibana #2.1部署ES群集 2.1.1基本配置 2.1.2安装Elasticsearch 2.1.3安装Logstash 2.1.4Filebeat 2.1.5安装Kibana 1.1ELK平台介绍 1.1.1ELK概述 ELK 是三个开源工具的缩写&#xff0c;分别是Elas…

Shiro漏洞复现

Shiro简介 Apache Shiro是一种功能强大且易于使用的Java安全框架&#xff0c;它执行身份验证、授权、 加密和会话管理&#xff0c;可用于保护任何应用程序的安全。 Shiro提供了应用程序安全性API来执行以下方面&#xff1a; 1.身份验证&#xff1a;证明用户身份&#xff0c;通…

VSCode 中使用 Google Test(GTest)框架测试

VSCode 中使用 Google Test&#xff08;GTest&#xff09;框架在 VSCode 中对 C 代码进行测试的示例&#xff1a; 一、Unbutu x86使用gtest 环境配置 安装 GTest &#xff1a;在 Ubuntu 系统中&#xff0c;可以通过命令sudo apt-get install libgtest-dev安装 GTest 库。对于…

【1.6 漫画数据库设计实战 - 从零开始设计高性能数据库】

1.6 漫画数据库设计实战 - 从零开始设计高性能数据库 &#x1f3af; 学习目标 掌握数据库表结构设计原则理解字段类型选择与优化学会雪花算法ID生成策略掌握索引设计与优化技巧了解分库分表设计方案 &#x1f4d6; 故事开始 小明: “老王&#xff0c;我总是不知道怎么设计数…

OSPF虚拟链路术语一览:快速掌握网络路由

大家好&#xff0c;这里是G-LAB IT实验室。今天带大家了解一下OSPF的相关知识&#xff01; 01 OSPF虚拟链路术语大全 网络架构中&#xff0c;OSPF&#xff08;开放式最短路径优先&#xff09;是一种重要的路由协议。通过其链路状态路由机制&#xff0c;OSPF能够有效维护和更新…

oracle常用的函数(一) 之 to_char、to_date

文章目录 前言to_char基本语法格式模型格式模型介绍无FM示例使用FM输出货币负数输出尖括号 将日期格式化将数字格式化为带有货币符号和千位分隔符的格式总结 to_date语法语法示例 戳这里&#xff0c;第二弹 → oracle常用的函数&#xff08;二&#xff09; 之 nvl、decode、l…

数据库服务器宕机的处理方法与实战策略

在当今数字化时代,数据库作为企业数据存储与管理的核心,承载着业务运行的关键信息。一旦数据库服务器宕机,将导致业务中断、数据丢失等严重后果,甚至可能给企业带来巨大的经济损失和声誉损害。因此,掌握一套系统、科学的数据库服务器宕机处理方法尤为重要。本文将从应急响…

如何hack边缘的kubelet修改Cgroup数值

之前做了一个VPA项目的需求&#xff0c;就是需要不重启的方式修改容器的Cgroup的值已达到垂直扩缩容的目的&#xff0c;项目中核心的思路如下 上游下发要VPA的结果的值写入到容器的Annotation里面Kubelet 感知到这个 annoation 的变化我们本地运行一个 Agent&#xff0c;里面运…

熟悉 PyCharm

界面 我们常用的就这个几个地方&#xff1a; 常用配置 调整字体大小 Ctrl 滚轮调整字体大小 插件推荐 Indent Rainbow 该插件的作用在于能够对于不同层级缩进的空格标注不同的颜色&#xff1a; 快捷键 快捷键的 pdf 下载链接&#xff1a; Windows 版&#xff1a;https:…

pytorch--模型训练的一般流程

文章目录 前言0、数据集准备1、数据集2、dataset3、model4、训练模型 前言 在pytorch中模型训练一般分为以下几个步骤&#xff1a; 0、数据集准备 1、数据集读取&#xff08;dataset模块&#xff09; 2、数据集转换为tensor&#xff08;dataloader模块&#xff09; 3、定义模型…

智能合同管理实战:基于区块链的电子签约技术实现

在数字经济时代,传统纸质合同签署方式已难以满足企业高效、安全、合规的业务需求。智能合同管理(Smart Contract Management)结合区块链技术,正在重塑电子签约流程,实现合同全生命周期的自动化、可追溯和防篡改。本文将深入探讨基于区块链的电子签约技术实现,涵盖核心架构…

设计模式精讲 Day 22:模板方法模式(Template Method Pattern)

【设计模式精讲 Day 22】模板方法模式&#xff08;Template Method Pattern&#xff09; 文章标签 设计模式, 模板方法模式, Java开发, 面向对象设计, 软件架构, 设计模式实战, Java应用开发 文章简述 模板方法模式是一种行为型设计模式&#xff0c;它通过定义一个算法的骨架…

如何在pytorch中使用tqdm:优雅实现训练进度监控

文章目录 为什么需要进度条&#xff1f;tqdm 简介基础用法示例深度学习中的实战应用1. 数据加载进度监控2. 训练循环增强版3. 验证阶段集成 高级技巧与最佳实践1. 自定义进度条样式2. 嵌套进度条&#xff08;多任务&#xff09;3. 分布式训练支持4. 与日志系统集成 性能优化建议…

Linux中的xxd命令详解

xxd 是一个 十六进制转储&#xff08;hex dump&#xff09;工具&#xff0c;通常用于将二进制文件转换为十六进制格式&#xff0c;或者反向转换&#xff08;十六进制→二进制&#xff09;。它是 vim 的一部分&#xff0c;但在大多数 Linux 系统&#xff08;如 Ubuntu&#xff0…

磐维数据库panweidb3.1.0单节点多实例安装

0 说明 业务科室提单需要在某台主机上部署多个单机磐维数据库&#xff0c;用于业务测试。以下内容展示如何在单节点安装多个磐维数据库实例。 1 部署环境准备 1.1 IP 地址及端口 instipport实例1192.168.131.1717700实例2192.168.131.1727700 在131.17上分别安装两个实例&…

转录组分析流程(三):功能富集分析

我们的教程主要是以一个具体的例子作为线索,通过对公共数据库数据bulk-RNA-seq的挖掘,利用生物信息学分析来探索目标基因集作为某种疾病数据预后基因的潜能及其潜在分子机制,同时在单细胞水平分析(对scRNA-seq进行挖掘)预后基因的表达,了解细胞之间的通讯网络,以期为该疾病…

全面掌握 tkinter:Python GUI 编程的入门与实战指南

在自动化、工具开发、数据可视化等领域&#xff0c;图形用户界面&#xff08;GUI&#xff09;往往是提升用户体验的重要方式。作为 Python 官方内置的 GUI 库&#xff0c;tkinter 以其轻量、跨平台、易于学习的特性成为初学者和轻量级应用开发者首选。 本文将以深入浅出的方式…

TDH社区开发版安装教程

&#xff08;注&#xff1a;本文章来源于星环官网安装手册&#xff09; 后面放置了视频和安装手册连接 1、硬件及环境要求 Docker17及以上版本&#xff0c;支持Centos&#xff0c;Ubuntu等系统&#xff08;注&#xff1a;这里我使用CentOS-7版本&#xff0c;最佳版本推荐为7.…

Linux基本命令篇 —— grep命令

grep是Linux/Unix系统中一个非常强大的文本搜索工具&#xff0c;它的名字来源于"Global Regular Expression Print"&#xff08;全局正则表达式打印&#xff09;。grep命令用于在文件中搜索包含特定模式的行&#xff0c;并将匹配的行打印出来。 目录 一、基本语法 二…