#mav-link #tokio #drones #uav #protocols #unmanned-aerial-vehicles

maviola

支持基本微服务的MAVLink高级通信库

8次发布

0.1.3 2024年8月9日
0.1.2 2024年4月8日
0.1.1 2024年3月26日
0.1.0-alpha12023年12月30日

#61 in 机器人

Download history 8/week @ 2024-05-18 1/week @ 2024-05-25 17/week @ 2024-06-29 44/week @ 2024-07-27 77/week @ 2024-08-03 35/week @ 2024-08-10

156每月下载

MIT/Apache

600KB
9K SLoC

马维奥拉

用Rust编写的MAVLink高级通信库。

🇺🇦 repository mirror crates.io docs.rs issues

仓库

目前,我们使用GitLab作为主要项目仓库,并使用GitHub作为官方镜像。

我们只接受在GitLab上的问题pull请求,但我们会尽最大努力保持GitHub讨论尽可能活跃。

镜像将始终包含最新的发布标签,并会自动更新。

简介

马维奥拉提供了通信节点、网络或设备等抽象,并实现了MAVLink协议的有状态功能:顺序、消息签名、自动心跳等。主要特性包括

  • 同步和异步API。后者基于Tokio
  • 支持 MAVLink 1MAVLink 2 协议版本,还可能存在支持这两个版本的协议无关通道。
  • Maviola 支持所有标准 MAVLink 语法,由相应的载货功能控制。
  • 可以通过 MAVSpec 生成额外的自定义语法。

这个库基于 Mavio,这是一个支持 no-std 的底层库。如果您正在寻找嵌入式设备的解决方案,那么 Mavio 可能是一个更好的选择。

安装

如果您想使用同步 API,可以使用以下命令安装 Maviola

cargo add maviola --features sync

对于异步 API

cargo add maviola --features async

用法

📖 如果您想了解如何使用 Maviola,请从阅读 Maviola Playbook 开始。以下部分只是简要介绍。

这个库提供了同步和异步 API。可以通过 sync 功能标志启用同步 API。异步 API 基于 Tokio,可以通过 async 功能标志启用。同步和异步 API 之间的差异很小,所以您可以在需要时轻松地在它们之间切换。还可能在不同部分的项目中使用同步和异步 API。

同步 API

安装

cargo add maviola --features sync

创建一个代表特定 MAVLink 设备的同步 TCP 服务器

use maviola::prelude::*;
use maviola::sync::prelude::*;

pub fn main() -> Result<()> {
    // Create a synchronous MAVLink node 
    // with MAVLink 2 protocol version
    let server = Node::sync::<V2>()
        .id(MavLinkId::new(17, 42))                     // Set device system and component IDs
        .connection(TcpServer::new("127.0.0.1:5600")?)  // Define connection settings
        .build()?;

    // Handle node events
    for event in server.events() {
        match event {
            // Handle a new peer
            Event::NewPeer(peer) => println!("new peer: {peer:?}"),
            // Handle a peer that becomes inactive
            Event::PeerLost(peer) => {
                println!("peer offline: {peer:?}");
                // Exit when all peers are disconnected
                if !server.has_peers() {
                    break;
                }
            }
            // Handle incoming MAVLink frame
            Event::Frame(frame, callback) => if server.validate_frame(&frame).is_ok() {
                // Handle heartbeat message
                if let Ok(Minimal::Heartbeat(msg)) = frame.decode::<Minimal>() {
                    // Respond with the same heartbeat message to all clients,
                    // except the one that sent this message
                    callback.respond_others(&server.next_frame(&msg)?)?;
                }
            }
            Event::Invalid(frame, err, callback) => {
                /* Handle invalid frame */
            }
        }
    }
}

异步 API

安装

cargo add maviola --features async

创建一个代表特定 MAVLink 设备的异步 TCP 服务器

use maviola::prelude::*;
use maviola::asnc::prelude::*;

#[tokio::main]
async fn main() -> Result<()> {
    // Create an asynchronous MAVLink node
    // with MAVLink 2 protocol version
    let server = Node::asnc::<V2>()
        .id(MavLinkId::new(17, 42))             // Set device system and component IDs
        .connection(
            TcpServer::new("127.0.0.1:5600")?   // Define connection settings
        )
        .build().await?;

    // Subscribe to a stream of node events
    let mut events = server.events().unwrap();
    // Handle node events
    while let Some(event) = events.next().await {
        match event {
            // Handle a new peer
            Event::NewPeer(peer) => println!("new peer: {peer:?}"),
            // Handle a peer that becomes inactive
            Event::PeerLost(peer) => {
                println!("peer offline: {peer:?}");
                // Exit when all peers are disconnected
                if !server.has_peers().await {
                    break;
                }
            }
            // Handle incoming MAVLink frame
            Event::Frame(frame, callback) => if server.validate_frame(&frame).is_ok() {
                // Handle heartbeat message
                if let Ok(Minimal::Heartbeat(msg)) = frame.decode::<Minimal>() {
                    // Respond with the same heartbeat message to all clients,
                    // except the one that sent this message
                    callback.respond_others(&server.next_frame(&msg)?)?;
                }
            }
            Event::Invalid(frame, err, callback) => {
                /* Handle invalid frame */
            }
        }
    }
    Ok(())
}

示例

基本示例可以在 这里 找到。

API 稳定性

尽管这个库的版本号很小,但 API 的大部分都被认为是稳定的。所有仍在考虑中的 API 部分都隐藏在 unstable Cargo 功能标志之下。

有几个例外,即 Device 实体。我们正在考虑在未来丰富其 API,不能保证此操作不会破坏现有的 API。在跟踪器中有一个相应的 问题

基本上,项目已经达到了这样的状态,即我们的直觉和我们的工程经验告诉我们,未来的开发将主要与添加新功能有关,而不是修改现有的功能。目前的计划是创建一个适当的 路线图,这样其他人就不必依赖我们含糊其辞的直觉。

您可以跟踪 v1 里程碑,该里程碑专门针对 API 稳定化。

许可证

在这里,我们只是遵循根据 Rust API 指南(C-PERMISSIVE)建议的双重许可。

以下任一许可证下:

由您选择。

贡献

除非您明确说明,否则根据 Apache-2.0 许可证定义的,您有意提交的任何贡献,都应如上所述双重许可,不附加任何额外条款或条件。

依赖项

~2–12MB
~125K SLoC