ArduPilot开源代码之AP_MSP

1. 源由

AP_MSP是处理MSP协议格式的报文数据应用类。

关于MSP协议格式,我们之前已经做过比较详细讨论,有兴趣具体了解,请查阅相关资料:

2. Library设计

2.1 启动代码

AP_Vehicle::setup
 └──> AP_MSP::init
     └──> hal.scheduler->thread_create(FUNCTOR_BIND_MEMBER(&AP_MSP::loop, void), "MSP", 1024, AP_HAL::Scheduler::PRIORITY_IO, 1)

整个应用框架通过以下两个函数实现:

  • AP_MSP::init //初始化
  • AP_MSP::loop //遍历轮训

2.2 支持特性

  • 支持SerialProtocol_MSP:通用MSP协议
  • 支持SerialProtocol_DJI_FPV:DJI FPV OSD协议
  • 支持SerialProtocol_MSP_DisplayPort:MSP Display Port

2.3 MSP DisplayPort v.s. DJI FPV OSD

MSP DisplayPort 和 DJI FPV OSD 协议之间的主要区别在于它们的应用领域和功能。以下是两者的详细对比:

  • MSP DisplayPort
    MSP(MultiWii Serial Protocol) DisplayPort 是一种用于传输飞行控制器和显示设备之间数据的协议。它主要用于发送实时飞行数据到显示器或OSD(On-Screen Display)。这是一个开源协议,广泛用于开源飞行控制器固件如Betaflight、iNav等。

特点:

  1. 开源协议:MSP 是开源的,允许开发者根据需要进行修改和扩展。
  2. 灵活性:可以传输各种类型的飞行数据,如GPS信息、电池状态、飞行模式等。
  3. 兼容性:与多种飞行控制器和OSD设备兼容,广泛应用于自制和定制无人机系统。
  • DJI FPV OSD
    DJI FPV OSD(On-Screen Display) 是由 DJI 提供的专有协议,专门用于其 FPV(First Person View)系统。这一协议用于在飞行时将实时飞行数据和视频传输到FPV眼镜或显示器上。

特点:

  1. 专有协议:DJI FPV OSD 是专有协议,专门为 DJI 的 FPV 产品设计。
  2. 集成性强:与 DJI 生态系统高度集成,提供无缝的用户体验。
  3. 功能丰富:提供高质量的视频传输和实时飞行数据,通常包括摄像头切换、飞行模式、GPS信息、电池状态等。
  • 主要差异
  1. 开放性

    • MSP DisplayPort 是开源协议,允许广泛的社区贡献和定制。
    • DJI FPV OSD 是闭源的,仅限于 DJI 设备使用。
  2. 应用范围

    • MSP DisplayPort 广泛应用于多种飞行控制器和显示设备。
    • DJI FPV OSD 专用于 DJI 的 FPV 系统。
  3. 兼容性

    • MSP DisplayPort 兼容多种设备和系统。
    • DJI FPV OSD 仅兼容 DJI 的产品。
  4. 功能与扩展性

    • MSP DisplayPort 提供了灵活的飞行数据传输,可以根据需要扩展。
    • DJI FPV OSD 集成了高质量的视频传输和各种飞行数据,但其扩展性受到限制,因为它是闭源的。

总体来说,MSP DisplayPort 更适合于那些需要灵活性和可定制性的开源无人机项目,而 DJI FPV OSD 则为使用 DJI 设备的用户提供了更集成和便捷的解决方案。

3. 重要例程

3.1 AP_MSP::init

AP_MSP::init
|
├── 获取串行管理器的引用 (const AP_SerialManager &serial_manager = AP::serialmanager())
|
├── 初始化 UART 指针 (AP_HAL::UARTDriver *uart = nullptr)
|
├── 初始化使用 MSP 线程的后端计数 (uint8_t backends_using_msp_thread = 0)
|
├── 定义支持的 MSP 协议数组 (static const AP_SerialManager::SerialProtocol msp_protocols[])
|   ├── AP_SerialManager::SerialProtocol_DJI_FPV
|   ├── AP_SerialManager::SerialProtocol_MSP
|   └── #if HAL_WITH_MSP_DISPLAYPORT
|       └── AP_SerialManager::SerialProtocol_MSP_DisplayPort
|       #endif
|
├── 遍历 MSP 协议数组 (for (const auto msp_protocol: msp_protocols))
|   ├── 遍历协议实例 (for (uint8_t protocol_instance=0; protocol_instance<MSP_MAX_INSTANCES-_msp_status.backend_count; protocol_instance++))
|       ├── 找到对应的串口 (uart = serial_manager.find_serial(msp_protocol, protocol_instance))
|       |
|       ├── 如果找到 UART 串口且初始化后端失败,则跳出当前循环 (if (uart != nullptr))
|       |   └── if (!init_backend(_msp_status.backend_count, uart, msp_protocol)) { break; }
|       |
|       ├── 如果后端使用 MSP 线程,增加使用 MSP 线程的后端计数 (if (_backends[_msp_status.backend_count]->use_msp_thread()))
|       |   └── backends_using_msp_thread++
|       |
|       └── 增加后端计数 (_msp_status.backend_count++)
|
└── 如果至少找到一个使用 MSP 线程的后端,启动协议处理线程 (if (backends_using_msp_thread > 0))
    └── if (!hal.scheduler->thread_create(FUNCTOR_BIND_MEMBER(&AP_MSP::loop, void), "MSP", 1024, AP_HAL::Scheduler::PRIORITY_IO, 1)) { return; }

3.2 AP_MSP::loop

AP_MSP::loop()
│
├── 初始化 UART (for loop)
│   ├── _backends[i] != nullptr && _backends[i]->use_msp_thread()
│   └── _backends[i]->init_uart()
│
├── 无限循环 while (true)
    ├── 延迟 hal.scheduler->delay(10)
    ├── 获取当前时间 const uint32_t now = AP_HAL::millis()
    ├── 闪烁逻辑
    │   ├── (uint32_t(now * 0.00143) & 0x01) != _msp_status.flashing_on
    │   └── (uint32_t(now * 0.0005) & 0x01) != _msp_status.slow_flashing_on
    ├── 检测飞行模式变化
    │   ├── AP::notify().flags.flight_mode != _msp_status.last_flight_mode
    │   └── now - _msp_status.last_flight_mode_change_ms > OSD_FLIGHT_MODE_FOCUS_TIME
    ├── 屏幕变化检测 (if OSD_ENABLED)
    │   └── osd != nullptr
    │       └── _msp_status.current_screen != screen || !_msp_status.osd_initialized
    │           └── update_osd_item_settings()
    └── 处理后台数据 (for loop)
        ├── _backends[i] != nullptr && _backends[i]->use_msp_thread()
        ├── _backends[i]->hide_osd_items()
        ├── _backends[i]->process_incoming_data()
        └── _backends[i]->process_outgoing_data()

3.3 AP_MSP::init_backend

AP_MSP::init_backend
|
|-- if (protocol == AP_SerialManager::SerialProtocol_MSP)
|   |-- 创建 AP_MSP_Telem_Generic 实例
|
|-- else if (protocol == AP_SerialManager::SerialProtocol_DJI_FPV)
|   |-- 创建 AP_MSP_Telem_DJI 实例
|
|-- #if HAL_WITH_MSP_DISPLAYPORT
|   |-- else if (protocol == AP_SerialManager::SerialProtocol_MSP_DisplayPort)
|       |-- 创建 AP_MSP_Telem_DisplayPort 实例
|
|-- else
|   |-- 返回 false
|
|-- if (_backends[backend_idx] != nullptr)
|   |-- 初始化后端实例
|   |-- 返回 true
|
|-- 返回 false

4. 实例理解

5. 总结

其实Ardupilot代码从框架设计的角度来看,非常透明、简洁、当然实际应用过程也存在一些资源剪裁问题。

总的来说,目前betaflight/inav开发航模生态下,MSP协议还是非常普及的。了解这块协议,对于兼容和集成会有很大的帮助。

6. 参考资料

【1】ArduPilot开源飞控系统之简单介绍
【2】ArduPilot之开源代码Task介绍
【3】ArduPilot飞控启动&运行过程简介
【4】ArduPilot之开源代码Library&Sketches设计
【5】ArduPilot之开源代码Sensor Drivers设计

相关推荐

  1. ArduPilot源代码AP_MSP

    2024-07-10 12:18:03       31 阅读
  2. ArduPilot源代码AP_OpticalFlow_MSP

    2024-07-10 12:18:03       26 阅读
  3. ArduPilot源代码AP_OpticalFlow_UPFLOW

    2024-07-10 12:18:03       24 阅读
  4. ArduPilot源代码AP_OpticalFlow_CXOF

    2024-07-10 12:18:03       31 阅读
  5. ArduPilot源代码OpticalFlow_backend

    2024-07-10 12:18:03       28 阅读
  6. ArduPilot源代码AP_AHRS_View

    2024-07-10 12:18:03       21 阅读
  7. ArduPilot源代码AP_DAL_GPS

    2024-07-10 12:18:03       22 阅读
  8. ArduPilot源代码AP_DAL_RangeFinder

    2024-07-10 12:18:03       20 阅读
  9. ArduPilot源代码AP_DAL研读系列

    2024-07-10 12:18:03       18 阅读
  10. ArduPilot开源飞控AP_VisualOdom

    2024-07-10 12:18:03       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 12:18:03       99 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 12:18:03       107 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 12:18:03       90 阅读
  4. Python语言-面向对象

    2024-07-10 12:18:03       98 阅读

热门阅读

  1. dify-on-wechat中涉及企业微信几个函数解析

    2024-07-10 12:18:03       29 阅读
  2. 【maya插件开发】vscode debug python 代码

    2024-07-10 12:18:03       26 阅读
  3. 【AI应用探讨】—主成分分析(PCA)应用场景

    2024-07-10 12:18:03       30 阅读
  4. 基数排序算法Python实现

    2024-07-10 12:18:03       25 阅读
  5. qt todoapp

    2024-07-10 12:18:03       26 阅读
  6. 如何减少开发过程中的bug-数据库篇

    2024-07-10 12:18:03       28 阅读
  7. 驻场运维的前途在哪里,这里有金玉良言

    2024-07-10 12:18:03       28 阅读
  8. 认字之 刬

    2024-07-10 12:18:03       19 阅读
  9. lvs集群

    lvs集群

    2024-07-10 12:18:03      28 阅读
  10. AUTOSAR:汽车软件架构的未来

    2024-07-10 12:18:03       26 阅读
  11. 相机光学(二十九)——显色指数(Ra)

    2024-07-10 12:18:03       23 阅读