#mav-link #drones #uav #protocols #no-alloc #async-io #send-receive

无std mavio

支持 no-stdno-alloc 目标的简约 MAVLink 客户端

10 个版本

0.2.6 2024 年 8 月 9 日
0.2.5 2024 年 3 月 26 日
0.2.0-rc12024 年 1 月 26 日
0.1.1 2024 年 1 月 11 日
0.1.0 2023 年 12 月 30 日

#35机器人

Download history 6/week @ 2024-04-28 2/week @ 2024-05-05 7/week @ 2024-05-12 22/week @ 2024-05-19 10/week @ 2024-05-26 13/week @ 2024-06-02 13/week @ 2024-06-09 16/week @ 2024-06-16 7/week @ 2024-06-23 49/week @ 2024-06-30 7/week @ 2024-07-14 1/week @ 2024-07-21 85/week @ 2024-07-28 115/week @ 2024-08-04 18/week @ 2024-08-11

220 每月下载量
用于 maviola

MIT/Apache

250KB
3.5K SLoC

Mavio

支持传输无关的 MAVLink 通信的简约库。它支持 no-std(和 no-alloc)目标。

🇺🇦 repository mirror crates.io docs.rs issues

仓库

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

我们只在 GitLab 上接受 问题合并请求,但我们会尽力让 GitHub 讨论 尽可能活跃。

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

简介

马维奥是一个用于构建更复杂工具的组件。它完全专注于一件事:为与使用 MAVLink 协议的所有设备进行正确通信,提供所需的最小功能集。

  • 支持 MAVLink 1MAVLink 2 协议版本。
  • 提供中间 MAVLink 数据包解码,以“帧”的形式存在,仅包含头部、校验和签名进行反序列化。这意味着客户端不需要解码整个消息进行路由和验证。
  • 通过利用由 MAVSpec 生成的 MAVLink 抽象,支持可选的高级消息解码。
  • 包括由 Cargo 功能启用的标准 MAVLink 方言。
  • 通过校验和实现消息验证。
  • 包括用于 消息签名 的工具。

换句话说,马维奥实现了 MAVLink 协议的所有 无状态 功能。这意味着它不提供对消息序列化、自动心跳等功能的支持。客户端需要自行实现这些协议部分或使用专门的库。我们决定将马维奥保持得尽可能简单和吸引人,就像一个 8 位旋律

同时,马维奥具有灵活性,并尽量少地强制规定。特别是

  • 它支持 自定义方言 或可能根本不使用方言(用于中间解码)。后者在只想简单地路由或签名消息时很有用。
  • 可以读取和写入实现 std::io::Readstd::io::Write 特性的任何内容。
  • no_std 目标兼容。在这种情况下,库提供了 ReadWrite 特性的简化版本。
  • 通过 Tokio 支持异步 I/O。
  • 允许过滤掉不必要的 MAVLink 实体(即消息、枚举、命令),以减少编译时间。

此库是 Mavka 工具链的一部分。它与以下项目集成

  • MAVInspect 负责解析 MAVLink XML 定义。
  • MAVSpec 专注于代码生成。马维奥使用此库生成 MAVLink 方言。
  • Maviola,是一个基于 Mavio 的 MAVLink 通信库,提供高级接口用于 MAVLink 消息,并处理协议的 有状态 功能:序列化、消息时间戳、自动心跳、简化消息签名等。

此项目遵循 语义版本控制。根据规范,在达到版本 1.0.0 之前,可以在次要版本中引入破坏性更改。然而,我们将在可能的情况下,将不稳定的功能保持在 unstable 功能标志下。

安装

使用 cargo 安装马维奥

cargo add mavio

用法

有关详细信息,请参阅 API 部分 和 API 文档

作为TCP客户端连接,接收10个帧,并解码任何接收到的HEARTBEAT消息

use std::net::TcpStream;

use mavio::{Frame, Receiver};
use mavio::dialects::minimal as dialect;
use dialect::Minimal;

fn main() -> mavio::errors::Result<()> {
    let mut receiver = Receiver::new(TcpStream::connect("0.0.0.0:5600")?);

    for i in 0..10 {
        let frame = receiver.recv_frame()?;

        if let Err(err) = frame.validate_checksum::<Minimal>() {
            eprintln!("Invalid checksum: {:?}", err);
            continue;
        }

        if let Ok(Minimal::Heartbeat(msg)) = frame::decode() {
            println!(
                "HEARTBEAT #{}: mavlink_version={:#?}",
                frame.sequence(),
                msg.mavlink_version,
            );
        }
    }
}

更详细的用例可以在tcp_client.rs示例中找到。

作为服务器监听TCP端口,使用MAVLink 2协议向任何连接的客户端发送10个HEARTBEAT消息,然后断开客户端。

use std::net::TcpStream;

use mavio::dialects::minimal as dialect;
use dialect::enums::{MavAutopilot, MavModeFlag, MavState, MavType};

use mavio::prelude::*;

fn main() -> Result<()> {
    let mut sender = Sender::new(TcpStream::connect("0.0.0.0:5600")?);

    // Create a TCP client sender
    let mut sender = Sender::new(TcpStream::connect("0.0.0.0:5600")?);
    // Create an endpoint that represents a MAVLink device speaking `MAVLink 2` protocol
    let endpoint = Endpoint::v2(MavLinkId::new(15, 42));

    // Create a message
    let message = dialect::messages::Heartbeat {
        type_: MavType::FixedWing,
        autopilot: MavAutopilot::Generic,
        base_mode: MavModeFlag::TEST_ENABLED & MavModeFlag::CUSTOM_MODE_ENABLED,
        custom_mode: 0,
        system_status: MavState::Active,
        mavlink_version: 3,
    };
    println!("MESSAGE: {message:?}");

    for i in 0..10 {
        // Build the next frame for this endpoint.
        // All required fields will be populated, including frame sequence counter.
        let frame = endpoint.next_frame(&message)?;

        sender.send_frame(&frame)?;
        println!("FRAME #{} sent: {:#?}", i, frame);
    }
}

查看tcp_server.rs以获取更详细的用例。

API说明

本节提供了一般的API概述。对于更详细的信息,请查看API文档

I/O

Mavio提供了两个基本的I/O原语:SenderReceiver。这些结构体发送和接收Frame实例。

SenderReceiver是针对std::io::Writestd::io::Read泛型的。这意味着您可以通过实现这些特性的各种传输来通信MAVLink消息,包括UDP、TCP、Unix套接字和文件。实现自定义传输也很容易。

对于no-std目标,Mavio提供了ReadWrite特性的自定义实现。您可以针对特定的硬件通信(如串行端口)实现它们。

对于异步I/O,Mavio提供了与它们的同步对应物类似工作的AsyncSenderAsyncReceiver。除了使用Tokio之外,它们的操作方式相同。要启用异步支持,请添加tokio功能标志。

编码/解码

在接收后,MAVLink Frame可以被验证并解码为MAVLink消息。帧可以在不进行解码的情况下被路由、签名或转发到另一个系统/组件ID。

注意!

MAVLink校验和验证需要CRC_EXTRA字节,它反过来依赖于方言规范。这意味着,如果您正在从嘈杂的源或实现过时消息规范的设备进行无方言路由,您可能会转发垃圾消息。在高延迟通道的情况下,您可能希望强制符合特定的方言以过滤不兼容的消息。

要将帧解码为MAVLink消息,您需要使用特定的方言。标准MAVLink方言可在mavio::dialects下找到,并且可以通过相应的功能标志启用

  • minimal — 这是暴露您的存在给其他MAVLink设备所需的最小方言。
  • standard — 是 minimal 方言的超集,几乎所有飞行栈都期望使用。
  • common — 最小可行方言,具有大多数功能,是其他未来丰富方言的基石。
  • ardupilotmega — 功能齐全的方言,由 ArduPilot 使用。在大多数情况下,如果您想识别现有飞行栈中使用的几乎所有 MAVLink 消息,则此方言通常是首选。
  • all — 包含所有其他标准方言(包括为测试目的而创建的方言)的元方言。保证 all 家族方言的命名空间不会冲突。
  • MAVLink XML 定义 中的其他方言:asluavavssuascsairlinkcubepilotdevelopmenticarousmatrixpilotpaparazziualbertauavionix。这些不包括 python_array_testtest 方言,这些应该手动生成或作为 all 元方言的一部分。

自定义方言

方言的具体实现由 MAVSpec 生成,有关详细信息,请参阅其 文档。如果您想生成自定义方言,还可以查看 build.rs

示例

./examples/sync/examples 中有同步 I/O 的示例

  • tcp_server.rs 是一个简单的 TCP 服务器,等待连接,发送和接收心跳
    cargo run --package mavio_examples_sync --example tcp_server
    
  • tcp_client.rs 是一个 TCP 客户端,连接到服务器,发送和接收心跳
    cargo run --package mavio_examples_sync --example tcp_client
    
  • tcp_ping_pong.rs 服务器和客户端通过 TCP 通信
    cargo run --package mavio_examples_sync --example tcp_ping_pong
    

./examples/async/examples 中有异步 I/O 的示例

  • async_tcp_ping_pong.rs 服务器和客户端通过 TCP 通信
    cargo run --package mavio_examples_async --example async_tcp_ping_pong
    

有关使用过滤后的 MAVLink 实体的自定义方言生成的示例,请参阅 ./examples/custom/examples

  • custom_dialects_usage.rs 是自定义生成的方言的基本用法
    cargo run --package mavio_examples_custom --example mavio_examples_custom_usage
    
  • custom_message.rs 创建和使用自定义消息
    cargo run --package mavio_examples_custom --example custom_message
    

许可

我们简单遵循根据 Rust API 指南(C-PERMISSIVE)的建议双许可。

在以下任一项下许可:

由您选择。

贡献

除非您明确声明,否则根据Apache-2.0许可证定义的任何有意提交以包含在作品中的贡献,将按上述方式双许可,不附加任何额外条款或条件。

依赖项

~1–3.5MB
~65K SLoC