APM 仿真遙控指南

地面站開發了一段時間了,由于沒有硬件,所以一直在 APM 模擬器中驗證。我們已經實現了 MAVLink 消息接收和解析,顯示無人機狀態,給無人機發送消息,實現一鍵起飛,飛往指定地點,降落,返航等功能,本期我們來看看如何在模擬器中實現對無人機的遙控。

【注意】

  1. 本期所說的遙控無人機都是指遙控無人機模擬器,不涉及硬件在環。
  2. 前方有墜機風險,請謹慎駕駛。

遙控的基本知識

遙控分為發送端和接收端,發送端自然是遙控器,接收方自然就是無人機。遙控信號一般是一系列數值,通過無線電傳輸。每個數值被稱為一個通道(channel),所以在無人機中,遙控信號一般也稱為 Radio Channel,簡稱 RC。通道個數以及每個通道的作用取決于軟件實現,比如 APM 共有18個通道。

無人機收到 RC 控制信號后,會通過飛控將其轉換為 PWM 信號,然后輸出給電調來控制電機轉速。飛控就是飛行控制模塊,是一個集成了多種傳感器的嵌入式系統,配有飛控固件,可以通過地面站設置固件參數,簡化了無人機的開發流程。

RC 信號可以理解為一個整數數組,其中有些來自搖桿,有些來自按鈕,通過遙控器發送給無人機。當然,除了遙控,地面站也能發送這個數組來模擬遙控控制,所以 RC 信號的來源是可以不唯一的。此外,遙控和地面站是不同的東西,雖然在物理上可以把它們封裝在一個盒子里。因為我用的是 AMP 模擬器,所以本期所講的內容也都是基于 APM 飛控平臺。

通過mavproxy遙控無人機

由于沒有無人機硬件,我首先想到的是能不能通過 mavproxy 來模擬遙控控制。mavproxy 的確提供了 rc 命令來手動控制無人機,但是官網上這部分資料不夠詳細,對新手不太友好。簡單來說就是我們可以通過 rc <channel> <value> 命令來修改某個 RC 通道的值,APM 共有 18 個通道,每個通道的范圍都是 0~65535 (2字節無符號整數),有效范圍是 1000~2000,對于搖桿,1500 表示中立位置,而 0 和 65536 具有特殊含義。

  • 0 表示將該通道的值釋放回遙控器。什么意思呢?也就是采用遙控器上對應通道的值,或者說將該通道的控制權交還給遙控器,為什么呢?因為 RC 輸入的來源可以不止是遙控器。
  • 65535 表示忽略該通道的值,通過地面站模擬遙控時,如果不想修改某些通道的值,就可以將這些通道的值都設置為 65535。

在 mavproxy 的控制臺,我們可以通過以下命令來查看各個通道的最小值,最大值和中立值,其中 x 是通道編號,取值為 1,2,3…等。

  • param fetch RCx_MIN :最小值。
  • param fetch RCx_MAX :最大值。
  • param fetch RCx_TRIM :中立值。

對于我現在的需求,用不到所有的通道,主要用到的是前4個通道,分別控制無人機的姿態和油門。至于為什么俯仰和偏航不是連著的,我也表示很好奇。

通道含義
RC11000~2000滾轉(roll)
RC21000~2000俯仰(pitch)
RC31000~2000油門(throttle)
RC41000~2000偏航(yaw)

首先我們還是通過一鍵起飛的方式讓無人機先飛起來,用 mavproxy 命令行或者 QGC 都可以。一鍵起飛之后,無人機會處于 guided 模式,這個模式下無人機會飛往地圖上點擊的位置或者指定的某個經緯度。 guided 模式不支持手動控制,手動模式是 manual ,在 APM 中,它等價于 stabilize 模式,也就是模擬器啟動時的默認模式。

不過在使用 mode 切換模式之前,我們需要先使用 rc 3 1500 命令將油門置于中立位置。因為 APM 模擬器啟動時,油門默認是處于最低位置的,也就是1000。如果此時直接切換到手動模式,無人機就會因失去動力而墜機,再現經典的“黑鷹墜落”。

Mayday, Mayday! Black Hawk is going down!

現在我們可以使用 mode stabilize 切換到手動模式了。然后我們可以通過 rc 3 1600 讓無人機上升, rc 3 1400 下降,或者通過 rc 1 1800 轉向。RC1 到 RC4 你可以都試試,如果你還開著 QGroundControl 地面站,可以通過姿態儀和指南針查看無人機狀態,因為 mavproxy 的地圖沒有姿態儀和指南針,所以 QGC 上會看得比較直觀。唯一需要注意的就是,小心墜機!

mode guided
arm throttle
takeoff 40rc 3 1500
mode stabilizerc 3 1600
rc 1 1800
... ...

我們已經學會了手動控制無人機飛行,那么能否直接手動起飛呢?

答案是肯定的。因為 APM 模擬器啟動時默認就出于 stabilize 模式,因此我們可以直接解鎖,然后轟油門起飛。

arm throttle
rc 3 1600

throttle 就是油門的意思, arm 是武裝的意思, arm throttle 就是解鎖油門。注意在無人機領域,系統狀態不是用”已上鎖“和”未上鎖“來描述,而是用”武裝“和”解除武裝“來描述。”鎖“表示安全,”武裝“表示危險,因此他們對狀態的表述是相反的,“武裝”的含義是解鎖,“解除武裝”是上鎖。

但是在實操上有個需要注意的點,那就是解鎖后需要馬上轟油門才能成功起飛,否則無人機會重新上鎖,導致起飛失敗。這個間隔時間很短,這可能跟我調快了仿真速度有關。這其實是因為無人機的自動鎖定機制,當無人機落地,電機停轉之后,會自動解除武裝,是無人機的一種安全保護機制。

如果來不及輸入命令,我們還可以先將油門設置為 1500,然后使用 arm throttle force 強制解鎖。

rc 3 1500
arm throttle force
rc 3 1600

如果不強制解鎖,而是使用 arm throttle ,模擬器就會報錯 Arm: Throttle (RC3) is not neutral ,意思是油門處于不正常位置,這也是出于對無人機的保護,防止彈射起步。如果在連續的操作過程中導致油門沒有處于最低位,在一鍵起飛的時候也會看到這個報錯,只需要用 rc 3 1000 將油門置于最低位即可。有時候報的錯可能不是 RC3,而是其他通道,也是通過 rc 命令將其設置到中立位置(1500)即可。曾經在網上看到過某些無人機在起飛之前要先將油門擋桿扒到最左,其實也是這個原因。

如果想查看 RC 輸入和電機輸出,可以點擊 mavproxy 圖形命令窗口(Console)菜單欄的 Tools 菜單。

在這里插入圖片描述

然后在彈出菜單中選擇 RC Inputs 或 Servo Outputs 就能看到每個 RC 通道的值和電機輸出了。

在這里插入圖片描述

上圖左邊就是初始時各 RC 通道的值。

通過代碼遙控無人機

知道如何手動控制無人機之后,我們還要知道是怎么實現的。我想知道 rc 命令是如何發送給無人機的呢?首先想到的是抓包,如果我們觀察 mavproxy 的啟動命令,會發現它設置了三個通信地址:

  • --sitl 127.0.0.1:5501
  • --master tcp:127.0.0.1:5760
  • --out 127.0.0.1:14550

14550 我們已經很熟悉了,這是 mavproxy 轉發 mavlink 消息的地址,也是其他地面站連接的地址。 5760 是與模擬器通信的地址, 5501 是與仿真環境通信的地址,也是 UDP 協議。

為了弄清 rc 命令背后的原理,我對 55015760 兩個端口進行了抓包,結果顯示 rc 命令是通過 5501 端口發送出去的。但問題是發送的數據并不是 mavlink 格式,而是下面這么一串數據。

在這里插入圖片描述

為了一探究竟,也只好去看看 mavproxy 的源碼了。 rc 命令的源碼在 MAVProxy/modules/mavproxy_rc.py 文件中,我們找到 cmd_cr 這個函數。

def cmd_rc(self, args):'''handle RC value override'''if len(args) > 0 and args[0] == 'set':self.rc_settings.command(args[1:])returnif len(args) == 1 and args[0] == 'clear':channels = self.overridefor i in range(self.count):channels[i] = 0self.set_override(channels)returnif len(args) == 1 and args[0] == "status":self.cmd_rc_status()returnif len(args) == 1 and args[0] == "guiin":if not mp_util.has_wxpython:print("No wxpython detected. Cannot show GUI")elif sys.version_info >= (3, 10) and sys.modules['wx'].__version__ < '4.2.1':print("wxpython needs to be >=4.2.1 on Python >=3.10. Cannot show GUI")elif not self.rcin_gui:from MAVProxy.modules.lib import wxrcself.rcin_gui = wxrc.RCStatus(panelType=wxrc.PanelType.RC_IN)returnif len(args) == 1 and args[0] == "guiout":if not mp_util.has_wxpython:print("No wxpython detected. Cannot show GUI")elif sys.version_info >= (3, 10) and sys.modules['wx'].__version__ < '4.2.1':print("wxpython needs to be >=4.2.1 on Python >=3.10. Cannot show GUI")elif not self.servoout_gui:from MAVProxy.modules.lib import wxrcself.servoout_gui = wxrc.RCStatus(panelType=wxrc.PanelType.SERVO_OUT)returnif len(args) != 2:print("Usage: rc <set|channel|all|clear|status|guiin|guiout> <pwmvalue>")returnvalue = int(args[1])if value > 65535 or value < -1:raise ValueError("PWM value must be a positive integer between 0 and 65535")if value == -1:value = 65535channels = self.overrideif args[0] == 'all':for i in range(self.count):channels[i] = valueelse:channel = int(args[0])if channel < 1 or channel > self.count:print("Channel must be between 1 and %u or 'all'" % self.count)returnchannels[channel - 1] = valueself.set_override(channels)

從這個函數中,能看到 rc 命令有很多子命令, channel 就是我們上一節提到的用法, all 可以用來設置所有通道的值。 rc status 可以打印出每個通道的值,但是注意它不是打印的真實通道值,而是本地的副本,默認都是0,如果通道沒有修改過,那么打印出來就會是0。而 rc guiinrc guiout 對應的其實就是上一節中 Tools 菜單下的 RC Inputs 和 Servo Outputs 兩個子菜單,用這兩個命令也能彈出對應的窗口。

回到函數的后半段,函數將命令中設置的 value 首先記錄到本地 channels 副本,然后調用了 set_override 函數設置通道值,該函數定義如下。

def set_override(self, newchannels):'''this is a public method for use by drone API or other scripting'''self.override = newchannelsself.override_counter = 10self.send_rc()def send_rc(self):'''send RC override packet'''if self.sitl_output:chan16 = self.override[:16]buf = struct.pack('<HHHHHHHHHHHHHHHH', *chan16)self.sitl_output.write(buf)else:chan18 = self.override[:18]self.master.mav.rc_channels_override_send(self.target_system,self.target_component,*chan18)

set_override 最終調用了 send_rc 函數,而在 send_rc 函數中,將 channels 發送了出去。因為我們啟動 mavproxy 時設置了 sitl 參數,所以這里會進入 if 分支,也就是將 RC 通道的值發送到了 5501 端口。而且這里對數據的序列化方式也是直接使用了 struct.pack'<HHHHHHHHHHHHHHHH' 是序列化方式, < 表示采用小端序,每個 H 表示兩個字節,也就是 chan16 數組里每個整數用兩字節表示,所以我們抓包時抓到 32 字節也就不足為奇了,將它們按每兩個字節拆開如下。

dc05 dc05 dd05 dc05 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

0x05dc 剛好就是十進制的 1500 ,第三個 0x05dd,而我測試用的命令正是 rc 3 1501

下一步我們需要在地面站中通過 mavlink 協議發送遙控信號實現手動控制無人機,這里有兩個消息比較重要。一是 RC_CHANNELS (65) ,他是 無人機向地面站發送的當前 RC 通道值。二是 RC_CHANNELS_OVERRIDE (70) ,它是地面站發送給無人機的 RC 控制消息。

一是 RC_CHANNELS (65) ,他是 無人機向地面站發送的當前 RC 通道值。

二是 RC_CHANNELS_OVERRIDE (70) ,它是地面站發送給無人機的 RC 控制消息。要實現手動控制無人機,發送這個消息就行了。

這里給出兩篇官方參考文章:

  • RC Input (aka Pilot Input) — Dev documentation
  • https://mavlink.io/zh/messages/common.html#RC_CHANNELS

看吧,一點都不難。


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

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

相關文章

C語言入門教程100講(4)輸入輸出

文章目錄 1. 什么是輸入輸出&#xff1f;2. 標準輸入輸出函數2.1 printf 函數2.2 scanf 函數 3. 格式化占位符4. 示例代碼代碼解析&#xff1a;輸出結果&#xff1a; 5. 常見問題問題 1&#xff1a;scanf 中的 & 是什么作用&#xff1f;問題 2&#xff1a;printf 和 scanf …

《信息系統安全》(第一次上機實驗報告)

實驗一 &#xff1a;網絡協議分析工具Wireshark 一 實驗目的 學習使用網絡協議分析工具Wireshark的方法&#xff0c;并用它來分析一些協議。 二實驗原理 TCP/IP協議族中網絡層、傳輸層、應用層相關重要協議原理。網絡協議分析工具Wireshark的工作原理和基本使用規則。 三 實…

城市街拍人像自拍電影風格Lr調色教程,手機濾鏡PS+Lightroom預設下載!

調色教程 城市街拍人像自拍的電影風格 Lr 調色&#xff0c;是利用 Adobe Lightroom 軟件&#xff0c;對在城市街景中拍攝的人像自拍照片進行后期處理&#xff0c;使其呈現出電影畫面般獨特的視覺質感與藝術氛圍。通過一系列調色操作&#xff0c;改變照片的色彩、明暗、對比等元…

自學Python創建強大AI:從入門到實現DeepSeek級別的AI

人工智能&#xff08;AI&#xff09;是當今科技領域最熱門的方向之一&#xff0c;而Python是AI開發的首選語言。無論是機器學習、深度學習還是自然語言處理&#xff0c;Python都提供了豐富的庫和工具。如果你夢想創建一個像DeepSeek這樣強大的AI系統&#xff0c;本文將為你提供…

Qt/C++項目積累:4.遠程升級工具 - 4.1 項目設想

背景&#xff1a; 桌面程序一般都支持遠程升級&#xff0c;也是比較常用的場景設計。如酷狗音樂的升級&#xff0c;會提供兩個選項&#xff0c;自動幫助安裝或是新版本提醒&#xff0c;由用戶來決定是否升級&#xff0c;都屬于遠程升級的應用及策略。 看看經過這塊的功能了解及…

(一)丶Windows安裝RabbitMQ可能會遇到的問題

一丶可能會忘了配置ERLang的環境變量 二丶執行命令時報錯 第一步 rabbitmq-plugins enable rabbitmq_management 第二部 rabbitmqctl status 三丶修改.erlang.cookie 文件 1.找到C盤目下的.erlang.cookie文件 C:\Users\admin\.erlang.cookie C:\Windows\System32\config\sys…

Amdahl 定律

Amdahl 定律是用來表示&#xff0c;當提高系統某部分性能時對整個系統的影響&#xff0c;其公式如下&#xff1a; a表示我們提升部分初始耗時比例&#xff0c;k是我們的提升倍率&#xff0c;通過這個公式我們可以輕松的得知對每一部分的提醒&#xff0c;對整個系統帶來的影響…

HW華為流程管理體系精髓提煉華為流程運營體系(124頁PPT)(文末有下載方式)

資料解讀&#xff1a;HW華為流程管理體系精髓提煉華為流程運營體系&#xff08;124頁PPT&#xff09; 詳細資料請看本解讀文章的最后內容。 華為作為全球領先的科技公司&#xff0c;其流程管理體系的構建與運營是其成功的關鍵之一。本文將從華為流程管理體系的核心理念、構建…

Powershell WSL導出導入ubuntu22.04.5子系統

導出Linux子系統 導出位置在C盤下,根據自己的實際情況更改即可Write-Host "export ubuntu22.04.5" -ForegroundColor Green wsl --export Ubuntu-22.04 c:\Ubuntu-22.04.tar 導入Linux子系統 好處是目錄可用在任意磁盤路徑,便于遷移不同的設備之間Write-Host &quo…

【Attention】SKAttention

SKAttention選擇核注意力 標題&#xff1a;SKAttention 期刊&#xff1a;IEEE2019 代碼&#xff1a; https://github.com/implus/SKNet 簡介&#xff1a; 動機:增大感受野來提升性能、多尺度信息聚合方式解決的問題&#xff1a;自適應調整感受野大小創新性:提出選擇性內核…

解決Popwindow寬高的問題。

問題 在使用Popwindow進行自定義的過程中&#xff0c;需要設置popwindow的寬高。但是寬高很多時候容易出問題。比如下面的例子。 布局文件如下 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.andr…

MySQL數據庫精研之旅第二期:庫操作的深度探索

專欄&#xff1a;MySQL數據庫成長記 個人主頁&#xff1a;手握風云 目錄 一、查看數據庫 二、創建數據庫 2.1. 語法 2.2. 示例 三、字符集編碼和校驗(排序)規則 3.1. 查看數據庫支持的字符集編碼 3.2. 查看數據庫支持的排序規則 3.3. 不同的字串集與排序規則對數據庫的…

基于deepseek的智能語音客服【第四講】封裝milvus數據庫連接池封裝

通過工廠模式創建鏈接 static {// 創建連接池工廠BasePooledObjectFactory<MilvusServiceClient> factory new BasePooledObjectFactory<MilvusServiceClient>() {Overridepublic MilvusServiceClient create() throws Exception {return new MilvusServiceClient…

STM32基礎教程——定時器

前言 TIM定時器&#xff08;Timer&#xff09;:STM32的TIM定時器是一種功能強大的外設模塊&#xff0c;通過時基單元&#xff08;包含預分頻器、計數器和自動重載寄存器&#xff09;實現精準定時和計數功能。其核心原理是&#xff1a;內部時鐘&#xff08;CK_INT&#xff09;或…

OpenCV旋轉估計(4)生成一個字符串表示的匹配圖函數 matchesGraphAsString()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 matchesGraphAsString 函數是OpenCV庫中的一部分&#xff0c;位于 cv::detail 命名空間下。這個函數的主要作用是生成一個字符串表示的匹配圖&am…

Android 根據Url使用Retrofit框架進行文件下載

一、背景 根據后端返回的url下載地址,去執行文件下載&#xff0c;將文件保存到SD卡。這里使用Retrofit網絡框架。 二、代碼實現 2.1、定義一個DownloadFileService interface DownloadFileService {StreamingGETsuspend fun downloadFile(Url fileUrl: String):ResponseBody…

NVMe(Non-Volatile Memory Express)詳解

一、NVMe的定義與核心特性 NVMe&#xff08;非易失性內存主機控制器接口規范&#xff09;是一種 基于PCIe總線的高性能存儲協議&#xff0c;專為固態硬盤&#xff08;SSD&#xff09;設計&#xff0c;旨在替代傳統的AHCI協議&#xff08;如SATA&#xff09;。其核心特性包括&a…

機器學習——KNN超參數

sklearn.model_selection.GridSearchCV 是 scikit-learn 中用于超參數調優的核心工具&#xff0c;通過結合交叉驗證和網格搜索實現模型參數的自動化優化。以下是詳細介紹&#xff1a; 一、功能概述 GridSearchCV 在指定參數網格上窮舉所有可能的超參數組合&#xff0c;通過交叉…

穩定運行的以Oracle NoSQL數據庫為數據源和目標的ETL性能變差時提高性能方法和步驟

提高基于Oracle NoSQL數據庫的ETL&#xff08;提取、轉換、加載&#xff09;性能時&#xff0c;主要從多個角度進行優化。 提高基于Oracle NoSQL數據庫的ETL性能需要綜合考慮多個方面&#xff0c;關鍵是減少不必要的I/O操作、優化數據轉換和加載過程、合理配置Oracle NoSQL數據…