1. 程式人生 > >PX4學習(3)——資訊流淺析 uorb&mavlink

PX4學習(3)——資訊流淺析 uorb&mavlink

之前我們已經談到系統框架,之前談到了定製自己功能的兩部:新增模組和修改資訊流。

 

鑑於資訊流的重要性,我們在這裡重新複習整理一下:看完之後你應該做到三點:

1、掌握uorb基本函式的使用

2、能夠新增自己的uorb

3、嘗試去探究一下uorb和mavlink

 


    下面開始先複習第一部分,uorb的基本函式:

 

    uORB(Micro Object Request Broker,微物件請求代理器)是PX4/Pixhawk系統中非常重要且關鍵的一個模組,它肩負了整個系統的資料傳輸任務,所有的感測器資料、GPS、PPM訊號等都要從晶片獲取後通過uORB進行傳輸到各個模組進行計算處理。實際上uORB是一套跨「程序

」 的IPC通訊模組。在Pixhawk中, 所有的功能被獨立以程序模組為單位進行實現並工作。而程序間的資料互動就由為重要,必須要能夠符合實時、有序的特點。 
  Pixhawk使用的是NuttX實時ARM系統,uORB實際上是多個程序開啟同一個裝置檔案,程序間通過此檔案節點進行資料互動和共享。程序通過命名的「匯流排」交換的訊息稱之為「主題」(topic),在Pixhawk 中,一個主題僅包含一種訊息型別,通俗點就是資料型別。每個程序可以「訂閱」或者「釋出」主題,可以存在多個釋出者,或者一個程序可以訂閱多個主題,但是一條總線上始終只有一條訊息。(注意一條總線上始終只有一條訊息,後來的資訊總會覆蓋掉前面的訊息)

應用層中操作基礎飛行的應用之間都是隔離的,這樣提供了一種安保模式,以確保基礎操作獨立的高級別系統狀態的穩定性。而溝通它們的就是uORB。

 

    下面是一些常用函式:

int orb_subscribe(const struct orb_metadata *meta)
功能:訂閱主題(topic);
說明:即使訂閱的主題沒有被公告,但是也能訂閱成功;但是在這種情況下,卻得不到資料,直到主題被公告;
這就是為什麼釋出資料之前需要先公告,公告相當於註冊吧。在訊息主題中,控制代碼用的很多,都是對控制代碼直接操作的。控制代碼的初始化是放在程序的初始化部分的。

引數:
meta:uORB元物件,可以認為是主題id;
返回值:
正確返回一個控制代碼,控制代碼是你自己定義的,初始化為-1,如int my_topic_sub=-1;

int my_topic_sub = orb_subscribe(ORB_ID(my_topic));

注意:訂閱的控制代碼常常起名為_sub指的就是subscribe,看到不要以為是sub副的意思;而釋出的主題,字尾常常是_pub是publish的意思。

 

int orb_set_interval(int handle, unsigned interval)
功能:設定訂閱的最小時間間隔;
說明:如果設定了,則在這間隔內釋出的資料將訂閱不到;需要注意的是,設定後,第一次的資料訂閱還是由起初設定的頻率來獲取。handle控制代碼,訂閱主題返回的控制代碼,interval間隔時間,系統常設定的是33ms,就是30hz的更新頻率。
 

訂閱了訊息主題,如何檢查資料更新了嗎?下面就是兩種方式,區別自己比較吧,之前我提到過。

 

int poll(struct pollfd fds[], nfds_t nfds, int timeout)

功能:監控檔案描述符(多個);
說明:timeout就是最大阻塞這麼長時間等待你的資料,因為我不可能一直等你,那樣豈不是什麼也幹不了,所以限制一個時間,就等這麼常時間。返回為0那就是時間都用完了也沒等到資料,>0就是時間內拿到了資料,<0那就是出錯了,看到沒有返回的是拿到你資料時我還剩多少阻塞時間。

輸入: 

fds:struct pollfd結構型別的陣列,程序可以同時等待很多個主題資料,當有資料更新時,判斷一下是誰
nfds:用於標記陣列fds中的結構體元素的總數量;
timeout:是poll函式呼叫阻塞的時間,單位:毫秒;
返回值:
>0:阻塞時間內拿到了資料;
==0:抱歉時間都用完了,也沒能拿到資料;
-1:poll函式呼叫失敗;

 

int orb_check(int handle, bool *updated)
功能:檢查一個主題資料有沒有更新,更新了updated會被設定為true。但一旦呼叫ob_copy來接收、處理過後,updated會被自動設定為false,所以這種方式資料只能被第一個人檢測到,後面人再檢測到時updated已經是fals。

 

    兩種方式檢查到資料已經更新了,怎麼取出,怎麼使用?

int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
功能:從訂閱的主題中獲取資料並將資料儲存到buffer中。meta訊息的ID,handle控制代碼,哪個控制代碼,你訂閱時返回的控制代碼,從訊息中拷貝資料放到buffer中。buffer是自己訊息的資料結構型別自己定義的。例:sensor_combined_s raw ;orb_copy(ORB_ID(sensor_combined), sensor_sub_fd, &raw);

 

    前面說的都是訂閱,那麼怎麼釋出?

orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data)
功能:先公告主題,相當於註冊,只要一次就行了。meta公告的訊息ID,data公告的原始資料。
說明:在釋出主題之前是必須的;否則訂閱者雖然能訂閱,但是得不到資料;

int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
功能:公告之後就可以釋出主題資料。meta公告的訊息ID,handle公告返回的控制代碼,這個控制代碼初始化為null,data釋出的資料,要釋出什麼資料,自己填充。

 

      至於使用例程自己去官網看吧,例程很多。

 

 

2、能夠新增自己的uorb

 

   下面講第二個問題,如何新增自己的主題。

1)在msg/下仿照其他檔案,寫自己的主題內容,msg的名字就是你訊息主題的名字

2)在cmakelist中新增你的msg檔名

之後再編譯,就會在build/src/moudle/uorb/topic中有你自定義的主題.h檔案。看看裡面的內容是不是和你自定義的msg內容一樣,還給你生成了主題的資料結構。當使用這個主題時,#include你的主題就可以使用它了。

 

 

3、探究一下uorb和mavlink

 


   Mavlink是目前最常見的無人機飛控協議之一。PX4對Mavlink協議提供了良好的原生支援。該協議既可以用於地面站(GCS)對無人機(UAV)的控制,也可用於UAV對GCS的資訊反饋。其飛控場景一般是這樣的:
a) 手工飛控:GCS -> (MavLink) -> UAV
b) 資訊採集:GCS <- (Mavlink) <- UAV
c) 自治飛控:User App -> (MavLink) -> UAV


   也就是說,如果你想實現地面站控制飛行,那麼由你的地面站使用Mavlink協議,通過射頻通道(或 wifi etc.)給無人機發送控制指令就可以了。如果你想實現無人機自主飛行,那麼就由你自己寫的應用(執行在無人機系統上)使用Mavlink協議給無人機發送本地的控制指令就可以了。

    然而,為實現飛控架構的靈活性,避免對底層實現細節的依賴,在PX4中,並不鼓勵開發者在自定義飛控程式中直接使用Mavlink,而是鼓勵開發者使用一種名為uORB((Micro Object Request Broker,微物件請求代理)的訊息機制。其實uORB在概念上等同於posix裡面的命名管道(named pipe),它本質上是一種程序間通訊機制。由於PX4實際使用的是NuttX實時ARM系統,因此uORB實際上相當於是多個程序(驅動級模組)開啟同一個裝置檔案,多個程序(驅動級模組)通過此檔案節點進行資料互動和共享。

    在uORB機制中,交換的訊息被稱之為topic,一個topic僅包含一種message型別(即資料結構)。每個程序(或驅動模組)均可“訂閱”或“釋出”多個topic,一個topic可以存在多個釋出者,而且一個訂閱者可也訂閱多個topic。而正因為有了uORB機制的存在,上述飛控場景變成了:

a) 手工飛控:GCS -> (MavLink) -> (uORB topic) -> UAV
b) 資訊採集:GCS <- (Mavlink) <- (uORB topic) <- UAV
c) 自治飛控:User App -> (uORB topic) -> (MavLink) -> UAV

    有了以上背景基礎,便可以自寫飛控邏輯了,僅需在PX4原始碼中,新增一個自定義module,然後使用uORB訂閱相關資訊(如感測器訊息等),併發布相關控制資訊(如飛航模式控制訊息等)即可。

    最後值得一提的是,在PX4系統中,還提供了一個名為mavlink的專用module,原始碼在firmware的src/modules/mavlink中,這貨與linux的控制檯命令工具集相當相似,其既可以作為ntt控制檯下的命令使用,又可作為系統模組載入後臺執行。其所實現的功能包括:1)uORB訊息解析,將uORB訊息實際翻譯為具體的Mavlink底層指令,或反之。2)通過serial/射頻通訊介面獲取或傳送Mavlink訊息,既考慮到了使用者自寫程式的開發模式,也適用於類似linux的指令碼工具鏈開發模式,使用起來很靈活。

 

4、還可以通過mavlink修改資訊流,地面站就是走這個,這個有時間再整理。