PIXHAWK(ardupilot4.52)上傳航點的bug

起因是查看飛控日志時發現地面站上傳的平行航線,在日志看到航線卻并不是平行的。

?然后對比了一下地面站上傳的航點信息跟飛控讀取到的航點信息

?發現經緯度只有前幾位能夠對應上,后幾位都對應不上,兩個點之間相差了50公分。地面站工程師認為地面站上傳的數據沒問題,是飛控解析的問題。

經檢測,地面站上傳航點任務用的是?MISSION ITEM (39),MISSION ITEM (39),在2020年就已經啟用了,都2025年了,為啥還要用已經廢棄了5年的消息?搞不懂。

但是該消息為啥會被棄用呢?

讓我們一起來看下飛控是怎么解析該消息的。

在上一章我學習到了飛控是在GCS_MAVLINK::handle_mission_item(const mavlink_message_t &msg)函數中進行解析航點任務的。

//libraries\GCS_MAVLink\GCS_common.cpp
void GCS_MAVLINK::handle_mission_item(const mavlink_message_t &msg) ///解析航點的
{mavlink_mission_item_int_t mission_item_int;bool send_mission_item_warning = false;if (msg.msgid == MAVLINK_MSG_ID_MISSION_ITEM) {mavlink_mission_item_t mission_item;mavlink_msg_mission_item_decode(&msg, &mission_item); MAV_MISSION_RESULT ret = AP_Mission::convert_MISSION_ITEM_to_MISSION_ITEM_INT(mission_item, mission_item_int);if (ret != MAV_MISSION_ACCEPTED) {const MAV_MISSION_TYPE type = (MAV_MISSION_TYPE)mission_item_int.mission_type;send_mission_ack(msg, type, ret);return;}send_mission_item_warning = true;} else {mavlink_msg_mission_item_int_decode(&msg, &mission_item_int);//解碼函數gcs().send_text(MAV_SEVERITY_CRITICAL,"ss%d %ld,%ld",msg_sum++,mavlink_msg_mission_item_int_get_x(&msg),mavlink_msg_mission_item_int_get_y(&msg));}const uint8_t current = mission_item_int.current;const MAV_MISSION_TYPE type = (MAV_MISSION_TYPE)mission_item_int.mission_type;if (type == MAV_MISSION_TYPE_MISSION && (current == 2 || current == 3)) {struct AP_Mission::Mission_Command cmd = {};MAV_MISSION_RESULT result = AP_Mission::mavlink_int_to_mission_cmd(mission_item_int, cmd);if (result != MAV_MISSION_ACCEPTED) {//decode failedsend_mission_ack(msg, MAV_MISSION_TYPE_MISSION, result);return;}// guided or change-altif (current == 2) {// current = 2 is a flag to tell us this is a "guided mode"// waypoint and not for the missionresult = (handle_guided_request(cmd) ? MAV_MISSION_ACCEPTED: MAV_MISSION_ERROR) ;} else if (current == 3) {//current = 3 is a flag to tell us this is a alt change only// add home alt if neededhandle_change_alt_request(cmd);// verify we received the commandresult = MAV_MISSION_ACCEPTED;}send_mission_ack(msg, MAV_MISSION_TYPE_MISSION, result);return;}// not a guided-mode reqestMissionItemProtocol *prot = gcs().get_prot_for_mission_type(type);if (prot == nullptr) {send_mission_ack(msg, type, MAV_MISSION_UNSUPPORTED);return;}if (send_mission_item_warning) {prot->send_mission_item_warning();}if (!prot->receiving) {send_mission_ack(msg, type, MAV_MISSION_ERROR);return;}prot->handle_mission_item(msg, mission_item_int);
}

?主要看這部分

//libraries\GCS_MAVLink\GCS_common.cpp
//void GCS_MAVLINK::handle_mission_item(const mavlink_message_t &msg)if (msg.msgid == MAVLINK_MSG_ID_MISSION_ITEM) {mavlink_mission_item_t mission_item;mavlink_msg_mission_item_decode(&msg, &mission_item);
//    gcs().send_text(MAV_SEVERITY_CRITICAL,"%d %f,%f",msg_sum++,mavlink_msg_mission_item_get_x(&msg),mavlink_msg_mission_item_get_y(&msg));
//    gcs().send_text(MAV_SEVERITY_CRITICAL, "x:%ld,y:%ld",(int32_t)(1.0e7f*mission_item.x),(int32_t)(1.0e7f*mission_item.y)); //這個跟地面站讀取的一致gcs().send_text(MAV_SEVERITY_CRITICAL, "x:%f,y:%f",(mission_item.x),(mission_item.y));MAV_MISSION_RESULT ret = AP_Mission::convert_MISSION_ITEM_to_MISSION_ITEM_INT(mission_item, mission_item_int);if (ret != MAV_MISSION_ACCEPTED) {const MAV_MISSION_TYPE type = (MAV_MISSION_TYPE)mission_item_int.mission_type;send_mission_ack(msg, type, ret);return;}send_mission_item_warning = true;}

?mavlink_msg_mission_item_decode(&msg, &mission_item);是將msg的Mavlink消息解析并存放到mission_item中,mission_item的定義為:

//ardupilot\build\CubeOrange\libraries\GCS_MAVLink\include\mavlink\v2.0\common\mavlink_msg_mission_item.h
typedef struct __mavlink_mission_item_t {float param1; /*<  PARAM1, see MAV_CMD enum*/float param2; /*<  PARAM2, see MAV_CMD enum*/float param3; /*<  PARAM3, see MAV_CMD enum*/float param4; /*<  PARAM4, see MAV_CMD enum*/float x; /*<  PARAM5 / local: X coordinate, global: latitude*/float y; /*<  PARAM6 / local: Y coordinate, global: longitude*/float z; /*<  PARAM7 / local: Z coordinate, global: altitude (relative or absolute, depending on frame).*/uint16_t seq; /*<  Sequence*/uint16_t command; /*<  The scheduled action for the waypoint.*/uint8_t target_system; /*<  System ID*/uint8_t target_component; /*<  Component ID*/uint8_t frame; /*<  The coordinate system of the waypoint.*/uint8_t current; /*<  false:0, true:1*/uint8_t autocontinue; /*<  Autocontinue to next waypoint*/uint8_t mission_type; /*<  Mission type.*/
} mavlink_mission_item_t;

其中的xy就是經緯度,將經緯度單獨輸出看一下

從輸出的數據可以看到,經緯度都有個規律是都只有7個數字,那是因為float數據只有7位精度。

?從飛控讀取到的航點信息確實是只有前6位數值是一致的。后面的數據為啥就不一致了呢?

繼續看后面飛控的使用

 MAV_MISSION_RESULT ret = AP_Mission::convert_MISSION_ITEM_to_MISSION_ITEM_INT(mission_item, mission_item_int);

mission_item用于這里了,MAV_MISSION_RESULT AP_Mission::convert_MISSION_ITEM_to_MISSION_ITEM_INT函數會將航點任務信息進一步使用。

D:\Ardupilot\4.5.1\4.5\git_ardupilot\ardupilot4.5.1\ardupilot\libraries\AP_Mission\AP_Mission.cpp
MAV_MISSION_RESULT AP_Mission::convert_MISSION_ITEM_to_MISSION_ITEM_INT(const mavlink_mission_item_t &packet,mavlink_mission_item_int_t &mav_cmd)
{// TODO: rename mav_cmd to mission_item_int// TODO: rename packet to mission_itemmav_cmd.param1 = packet.param1;mav_cmd.param2 = packet.param2;mav_cmd.param3 = packet.param3;mav_cmd.param4 = packet.param4;mav_cmd.z = packet.z;mav_cmd.seq = packet.seq;mav_cmd.command = packet.command;mav_cmd.target_system = packet.target_system;mav_cmd.target_component = packet.target_component;mav_cmd.frame = packet.frame;mav_cmd.current = packet.current;mav_cmd.autocontinue = packet.autocontinue;mav_cmd.mission_type = packet.mission_type;/*the strategy for handling both MISSION_ITEM and MISSION_ITEM_INTis to pass the lat/lng in MISSION_ITEM_INT straight through, andfor MISSION_ITEM multiply by 1e7 here. We need an exception forany commands which use the x and y fields not aslatitude/longitude.*/if (!cmd_has_location(packet.command)) {mav_cmd.x = packet.x;mav_cmd.y = packet.y;} else {//these commands use x and y as lat/lon. We need to// multiply by 1e7 to convert to int32_tif (!check_lat(packet.x)) {return MAV_MISSION_INVALID_PARAM5_X;}if (!check_lng(packet.y)) {return MAV_MISSION_INVALID_PARAM6_Y;}mav_cmd.x = packet.x * 1.0e7f;mav_cmd.y = packet.y * 1.0e7f;}return MAV_MISSION_ACCEPTED;
}

可以看到經緯度最終都 *1.0e7,而經緯度都是float數據,這里放大了100萬倍,那么精度就丟失了。如:

?就這樣精度丟失,最終導致地面站上傳的航點跟實際的航點相差50公分!

對于這個bug,官網的解決方法就是直接棄用該MISSION ITEM (39),改成MISSION ITEM INT(73),將經緯度由float改成整型數據,以保障精度問題。

至于怎么保障float的精度問題也有其他方法(僅作為個人意見):

如地面站上傳的float數值小于7位:

?

但這樣會導致飛控無法做到精準導航,故不可取。

其二是在放大時先保障當前精度后再進行處理

但同樣ff數值也只能保障前7位數值,導致飛控無法做到精準導航,故不可取。

?

?

?當然也可以用double數據

但官網沒有該類型。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/89179.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/89179.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/89179.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

車載ECU刷寫文件格式匯總詳解

我是穿拖鞋的漢子&#xff0c;魔都中堅持長期主義的汽車電子工程師。 老規矩&#xff0c;分享一段喜歡的文字&#xff0c;避免自己成為高知識低文化的工程師&#xff1a; 做到欲望極簡&#xff0c;了解自己的真實欲望&#xff0c;不受外在潮流的影響&#xff0c;不盲從&#x…

Redis核心知識詳解:從全局命令到高級數據結構

一、Redis全局命令詳解 1.1 鍵查看與管理 dbsize&#xff1a;高效獲取鍵總數&#xff08;O(1)操作&#xff09; 127.0.0.1:6379> dbsize (integer) 8 keys&#xff1a;生產環境避免使用&#xff08;O(n)操作&#xff09; # 查找user開頭的鍵&#xff08;不推薦生產使用…

【網絡】Linux 內核優化實戰 - net.ipv4.tcp_mem

目錄 參數結構與含義與緩沖區大小參數的區別內存管理機制詳解1. 內存使用狀態與觸發邏輯2. 與其他參數的協同關系 典型調整場景與配置示例場景 1&#xff1a;高并發低帶寬服務&#xff08;如 API 網關&#xff0c;數萬連接但單連接流量小&#xff09;場景 2&#xff1a;高帶寬低…

插入排序的簡單介紹

今天給大家簡單介紹一下插入排序。 插入排序&#xff0c;其基本思想是將未排序的數據逐步插入到已排序序列中的合適位置&#xff0c;從而使整個序列逐漸有序。 下面我們看一個排序的過程&#xff08;升序&#xff09;&#xff0c;給定一個int類型的數組&#xff0c;利用插入排…

docker搭建minio和python使用minio

1 準備工作 1.創建目錄 [rootk8s-storage tmp]# mkdir -pv minio/{data,conf} mkdir: created directory ‘minio’ mkdir: created directory ‘minio/data’ mkdir: created directory ‘minio/conf’[rootk8s-storage minio]# chmod 777 -R *2.生成https證書 openssl req…

開源代碼修復新標桿——月之暗面最新開源編程模型Kimi-Dev-72B本地部署教程,自博弈修復 Bug

一、介紹 Kimi-Dev-72B是由月之暗面&#xff08;Moonshot AI&#xff09;最新開源的AI編程模型&#xff0c;專為軟件工程任務設計&#xff0c;并登頂 SWE-bench Verified 基準測試榜首&#xff0c;超越 DeepSeek-R1 等模型&#xff0c;成為當前開源代碼模型的 SOTA&#xff1a…

微服務架構之基本設計原則

作為系統架構師&#xff0c;在進行架構設計時需要遵循一系列經過實踐驗證的核心原則&#xff0c;這些原則貫穿于需求分析、模塊劃分、技術選型和系統演進的全流程。以下從核心設計原則、架構特性原則、工程實踐原則三個維度&#xff0c;結合具體案例展開說明&#xff1a; 一、…

Wpf布局之WrapPanel面板!

文章目錄 前言一、引言二、使用步驟 前言 Wpf布局之WrapPanel面板&#xff01; 一、引言 WrapPanel面板以一次一行或一列的方式布置控件&#xff01; 二、使用步驟 WrapPanel面板Orientation屬性默認是"Horizontal"&#xff0c;將控件從左向右進行排列&#xff…

QEMU運行RISCV版Ubuntu

宿主機為ubuntu20.04&#xff0c;推薦ubuntu 20.04 risc-v版&#xff0c; 宿主機為ubuntu24.04&#xff0c;推薦ubuntu 24.04 risc-v版&#xff0c; 安裝ubuntu 24.04 risc-v基本步驟&#xff1a; 1&#xff0c; sudo apt update sudo apt install opensbi qemu-system-misc…

【LeetCode 熱題 100】239. 滑動窗口最大值——(解法一)滑動窗口+暴力解

Problem: 239. 滑動窗口最大值 題目&#xff1a;給你一個整數數組 nums&#xff0c;有一個大小為 k 的滑動窗口從數組的最左側移動到數組的最右側。你只可以看到在滑動窗口內的 k 個數字。滑動窗口每次只向右移動一位。返回滑動窗口中的最大值 。 文章目錄 整體思路完整代碼時空…

攻防世界-MISC-red_green

知識點 1.pngLSB隱寫 步驟 方法一&#xff1a;zsteg 打開附件&#xff0c;是一張圖片&#xff0c;打開看不懂&#xff08;其實由兩種顏色構成&#xff0c;0和1&#xff09;&#xff0c;用zsteg查看&#xff0c;發現隱寫了一張jpg圖片&#xff0c;使用zsteg提取。打開jpg圖片…

歸因問答-如何進行自動評估

歸因模型函數g的形式化表示 輸入&#xff1a;用戶問題q 輸出&#xff1a;(a, p), 其中a為答案&#xff0c;p為原始文章中支持答案a的段落。 1&#xff09;單樣本歸因 針對輸入問題q&#xff0c;如何評估歸因模型g輸出中段落p是對答案a的正確歸因。 在論文arributed qa中&…

基于vue+View UI的組織機構選擇

1、效果 1、代碼 <template><Button type"primary" click"modal true">點擊選擇</Button><div v-if"selectedArr.length > 0"><p>已選擇項&#xff1a;</p><div v-for"(item, index) in sel…

人大金倉Kingbase數據庫KSQL 常用命令指南

人大金倉Kingbase數據庫KSQL 常用命令指南 1. 連接與基本操作 1.1 連接數據庫 # 基礎語法 ksql -U 用戶名 -d 數據庫名 -h 主機名 -p 端口號 # 示例 ksql -U system -d testdb -h 127.0.0.1 -p 543211.2 執行SQL腳本 # 基礎語法 ksql -U <用戶名> -W -f <SQL腳本文…

從萌芽到領航:廣州華銳互動的 AR 奮進之路?

在 AR 技術這片充滿無限可能的領域中&#xff0c;廣州華銳互動數字科技有限公司宛如一顆耀眼的新星&#xff0c;熠熠生輝。廣州華銳互動成立于 2008 年&#xff0c;在那個 AR 技術尚處于萌芽階段、大眾認知度還較低的時期&#xff0c;廣州華銳互動便憑借著前瞻性的戰略眼光和對…

redisson看門狗實現原理

Redisson 看門狗&#xff08;Watch Dog&#xff09;機制實現原理 Redisson 的 Watch Dog 機制是分布式鎖的核心組件之一&#xff0c;用于 自動續期 鎖的過期時間&#xff0c;防止業務邏輯執行時間超過鎖的持有時間&#xff0c;導致鎖提前釋放而引發并發問題。以下是其實現原理…

C++中explicit詳解

文章目錄 1. **防止隱式類型轉換**示例1&#xff1a;沒有使用explicit示例2&#xff1a;使用explicit 2. **防止拷貝初始化**示例1&#xff1a;沒有使用explicit示例2&#xff1a;使用explicit 3. **防止隱式類型轉換的鏈式調用**示例1&#xff1a;沒有使用explicit示例2&#…

代碼部落 20250629 CSP-J復賽 模擬賽

網址&#xff1a;代碼部落 一&#xff1a; 相濡以沫 β&#xff08;代碼請自寫&#xff09; 簽到題&#xff0c;如果a[i]<a[i1] a[i]a[i1],反之&#xff0c;直接輸出No 二 共同富裕&#xff08;代碼請自寫&#xff09; 簽到題&#xff0c;用sort前綴和 如果最富有的個…

零基礎學習RabbitMQ(5)--工作模式(1)

在前面的章節中我們簡單介紹過一些RabbitMQ的工作模式&#xff0c;RabbitMQ共提供了七種工作模式進行消息傳遞&#xff0c;這里我們來詳細介紹。 1. Simple(簡單模式) P&#xff1a;生產者 C&#xff1a;消費者 特點&#xff1a;一個生產者一個消費者&#xff0c;消息只能被…

Android Liunx ffmpeg交叉編譯

本文的交叉編譯在window上安裝VMware&#xff0c;使用Ubuntu20.4進行的編譯。 一、安裝NDK&#xff1a; 1、下載解壓&#xff1a; 在NDK 下載 | Android NDK | Android Developers下載Liunx平臺的NDK。 本人下載的是android-ndk-r27c-linux.zip版本的。 解壓android-ndk-r…