首先附上mavlink的各個消息的簡介https://pixhawk.ethz.ch/mavlink/(這里的內容很多,建議大概了解mavlink后再去瀏覽),
mavlink協議介紹http://qgroundcontrol.org/mavlink/start
之后會在我的資源里上傳一份為初學者准備的mavlink資料(轉載)已經上傳至筆者資源,免費下載。mavlink 純小白教程(英文)它用通俗的說法幫助新人理解什么是mavlink,mavlink能干嘛等等。資料只有第一部分,第二部分筆者沒有找到(可能是原作者沒繼續第二部分吧)。
先簡單介紹下mavlink協議。Mavlink協議最早由 蘇黎世聯邦理工學院 計算機視覺與幾何實驗組 的 Lorenz Meier 於2009年發布,並遵循LGPL開源協議。Mavlink協議是在串口通訊基礎上的一種更高層的開源通訊協議,主要應用在微型飛行器(micro aerial vehicle)的通訊上。Mavlink是為小型飛行器和地面站(或者其他飛行器)通訊時常常用到的那些數據制定一種發送和接收的規則並加入了校驗 (checksum)功能。
【1】下面開始說介紹mavlink所發送的數據結構。Mavlink傳輸時的基本單位是消息幀。


【2】下面主要介紹mavlink里消息的種類和如何看懂開始時提到的那個官方的mavlink消息介紹。
(一)中已經提到了在mavlink消息幀里最重要的兩個東西,一個是msgid;一個是payload,前者是payload中內容的編號,后者則存放了消息。消息有許多種類型,在官網的網頁中中以藍色的“#”加數字的方式來表示消息的編號如 “#0”(這樣的表示方法應該是為了方便在網頁中查找相應編號消息的定義)。在官網介紹網頁里往下拉,大概拉到二分之一的位置處,開始出現“MAVLink Messages”的介紹,往下看是各種消息的數據組成說明。下面將以幾個消息為例,講解mavlink消息。
先以 #0 消息為例,這個消息叫心跳包(heartbeat)。它一般用來表明發出該消息的設備是活躍的,飛行器和地面站都會發出這個信號(一般以1Hz發送),地面站和飛行器會根據是否及時收到了心跳包來判斷是否和飛行器或地面站失去了聯系。
從圖上可以看出,心跳包由6個數據組 成,第一個是占一個字節的飛行器類型數據(type),這個數據表示了當前發消息的是什么飛行器,比如四旋翼,固定翼等等。type的取值如何與飛行器類 型對應,這要在官方的mavlink消息介紹網頁上找,位於網頁開始出的數據枚舉中。如下圖所示:
第四個參數是用戶模式(custom mode),大概說一下Pixhawk的用戶模式。以多軸為例。它分為主模式(main mode)和子模式(sub mode),兩種模式組合在一起成為最終的模式,主模式分為3種,手動(manual),輔助(assist),自動(auto)。手動模式類似apm的姿態模式。在輔助模式中,又分為高度控制模式(altctl)和位置控制模式(posctl)兩個子模式,高度控制模式就類似apm的定高模式,油門對應到飛行器高度控制上。位置模式控制飛行器相對地面的速度,油門和高度控制模式一樣,yaw軸控制和手動模式一樣。自動模式里又分為3個子模式,任務模式(mission),留待模式(loiter),返航模式(return), 任務模式就是執行設定好的航點任務,留待模式就是gps懸停模式,返航模式就是直線返回home點並自動降落。在apm里這個參數貌似是沒有用的,注意這 個數據占了4個字節,在Pixhawk中,前兩個字節(低位)是保留的,沒有用,第三個字節是主模式,第四個字節是子模式。普通用戶請無視,開發者請注意:官網給出的通過程序設置模式的代碼是錯誤的。如圖,最后一行代碼有誤,應該為:

#76消 息(command long),該消息是發送長命令,一般是地面站發送給飛控命令用的。該消息組成如下圖。目標系統(命令的接收方,就是目標系統編號sysid),目標單元 (命令的接收單元,就是目標單元編號compid)。command數據是這條命令的編號,用於區別不同的命令。confirmation數據,筆者還不 是很明白,大概是是否需要收到命令后回復確認信號的意思。接下去有七個參數,這些參數是執行這條命令所需要告訴飛控的,許多命令都用不到七個參數,多余的 參數清0就可以了。
現 在應該對介紹mavlink官網的布局有所了解了吧。網頁前面主要講了各類數據的取值和含義,比如飛控類型(mav_autopilot),飛行器類型 (mav_type)等,其中mav_cmd是比較特殊和重要的一種數據。網頁的后半部分主要講了mavlink消息的種類和數據組成,這里會用到各種數 據,具體數據定義的可以回到前半部分去找。但是mavlink是個通用的通訊協議,不同的飛控支對mavlink支持方式不一樣,一般都只支持一部分mavlink消息,還會自己擴展一些mavlink協議所沒有定義的消息(pixhawk和apm都是如此),具體都以飛控代碼為准。

typedef struct __mavlink_heartbeat_t
{
uint32_t custom_mode; ///< A bitfield for use for autopilot-specific flags.
uint8_t type; ///< Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM)
uint8_t autopilot; ///< Autopilot type / class. defined in MAV_AUTOPILOT ENUM
uint8_t base_mode; ///< System mode bitfield, see MAV_MODE_FLAG ENUM in mavlink/include/mavlink_types.h
uint8_t system_status; ///< System status flag, see MAV_STATE ENUM
uint8_t mavlink_version; ///< MAVLink version, not writable by user, gets added by protocol because of magic data type: uint8_t_mavlink_version
} mavlink_heartbeat_t;
static inline void mavlink_msg_heartbeat_send(mavlink_channel_t chan, uint8_t type, uint8_t autopilot, uint8_t base_mode, uint32_t custom_mode, uint8_t system_status)
其中的chan是channel的縮寫,用於選擇發送的串口或者usb口。type就是飛行器類型,其余參數不明的可以看看本博客的上面文章。
該函數功能是將傳入的各個參數按照對應的格式放到heartbeat消息包中(即打包)
這個函數內部有一句預處理:
#if MAVLINK_CRC_EXTRA
是說是否使用額外的crc校驗字符(默認使用),詳情請看第一篇博客中對於兩個校驗字節的說明。
函數中會調用函數【2】
_mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HEARTBEAT, buf, MAVLINK_MSG_ID_HEARTBEAT_LEN, MAVLINK_MSG_ID_HEARTBEAT_CRC);
MAVLINK_MSG_ID_HEARTBEAT
//這個是心跳包消息對應的編號 這里=0
MAVLINK_MSG_ID_HEARTBEAT_LEN//這個是心跳包的長度 注意這個長度僅僅是payload的長度,不包括幀的頭尾。
MAVLINK_MSG_ID_HEARTBEAT_CRC//這個是heartbeat消息對應的額外的crc校驗碼 這里=50
如果只是想將對應的心跳包參數按照心跳包的格式存放好,則可以只調用
static inline uint16_t mavlink_msg_heartbeat_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg,
uint8_t type, uint8_t autopilot, uint8_t base_mode, uint32_t custom_mode, uint8_t system_status)
MAVLINK_HELPER uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status)
typedef struct __mavlink_message {
uint16_t checksum; ///< sent at end of packet
uint8_t magic; ///< protocol magic marker
uint8_t len; ///< Length of payload
uint8_t seq; ///< Sequence of packet
uint8_t sysid; ///< ID of message sender system/aircraft
uint8_t compid; ///< ID of the message sender component
uint8_t msgid; ///< ID of message in payload
uint64_t payload64[(MAVLINK_MAX_PAYLOAD_LEN+MAVLINK_NUM_CHECKSUM_BYTES+7)/8];
}