ArduPilot开源代码之AP_OSD_SITL

1. 源由

前面讨论了

本章将针对具体的AP_OSD_SITL类进行研讨。

2. 结构设计

2.1 成员变量

新增的变量主要用于模拟器的仿真OSD显示。

    sf::RenderWindow *w;

    sf::Texture font[256];
    uint8_t last_font;

    // setup to match MAX7456 layout
    static const uint8_t char_width = 12;
    static const uint8_t char_height = 18;
    uint8_t video_lines;
    uint8_t video_cols;
    static const uint8_t char_spacing = 0;

    // scaling factor to make it easier to read
    static const uint8_t char_scale = 2;
    uint8_t *buffer;

    pthread_t thread;
    HAL_Semaphore mutex;
    uint32_t counter;
    uint32_t last_counter;

2.2 OSD 符号

无自定义,将会保持与 AP_OSD_Backend 一致。

2.3 图形线程

  • void update_thread()
  • static void *update_thread_start(void *obj)
// main loop of graphics thread
void AP_OSD_SITL::update_thread(void)
{
    load_font();
    {
        WITH_SEMAPHORE(AP::notify().sf_window_mutex);
        w = NEW_NOTHROW sf::RenderWindow(sf::VideoMode(video_cols*(char_width+char_spacing)*char_scale,
                                               video_lines*(char_height+char_spacing)*char_scale),
                                 "OSD");
    }
    if (!w) {
        AP_HAL::panic("Unable to create OSD window");
    }

    while (true) {
        {
            WITH_SEMAPHORE(AP::notify().sf_window_mutex);
            sf::Event event;
            while (w->pollEvent(event)) {
                if (event.type == sf::Event::Closed) {
                    w->close();
                }
            }
            if (!w->isOpen()) {
                break;
            }
            if (counter != last_counter) {
                last_counter = counter;

                uint8_t buffer2[video_lines][video_cols];
                {
                    WITH_SEMAPHORE(mutex);
                    memcpy(buffer2, buffer, sizeof(buffer2));
                }
                w->clear();

                for (uint8_t y=0; y<video_lines; y++) {
                    for (uint8_t x=0; x<video_cols; x++) {
                        uint16_t px = x * (char_width+char_spacing) * char_scale;
                        uint16_t py = y * (char_height+char_spacing) * char_scale;
                        sf::Sprite s;
                        uint8_t c = buffer2[y][x];
                        s.setTexture(font[c]);
                        s.setPosition(sf::Vector2f(px, py));
                        s.scale(sf::Vector2f(char_scale,char_scale));
                        w->draw(s);
                    }
                }

                w->display();
                if (last_font != get_font_num()) {
                    load_font();
                }
            }
        }
        usleep(10000);
    }
}

3. 接口设计

3.1 一次性接口

3.1.1 init

创建图形线程。

// initialise backend
bool AP_OSD_SITL::init(void)
{
    pthread_create(&thread, NULL, update_thread_start, this);
    return true;
}

3.1.2 osd_thread_run_once

无,使用AP_OSD_Backend::osd_thread_run_once

3.1.3 init_symbol_set

无,使用AP_OSD_Backend::init_symbol_set

3.1.4 probe

最初的初始化,直接在AP_OSD::init_backend中进行,详见:ArduPilot开源代码之AP_OSD

AP_OSD_Backend *AP_OSD_SITL::probe(AP_OSD &osd)
{
    AP_OSD_SITL *backend = NEW_NOTHROW AP_OSD_SITL(osd);
    if (!backend) {
        return nullptr;
    }
    if (!backend->init()) {
        delete backend;
        return nullptr;
    }
    return backend;
}

3.2 基本操作

3.2.1 write

直接写入界面缓存中。

void AP_OSD_SITL::write(uint8_t x, uint8_t y, const char* text)
{
    if (y >= video_lines || text == nullptr) {
        return;
    }
    WITH_SEMAPHORE(mutex);

    while ((x < video_cols) && (*text != 0)) {
        getbuffer(buffer, y, x) = *text;
        ++text;
        ++x;
    }
}

3.2.2 flush

只有当counter发生变化时,图形线程才会刷新OSD。

void AP_OSD_SITL::flush(void)
{
    counter++;
}

3.2.3 clear

缓存清零,相当于OSD清空。

void AP_OSD_SITL::clear(void)
{
    AP_OSD_Backend::clear();
    WITH_SEMAPHORE(mutex);
    memset(buffer, 0, video_cols*video_lines);
}

3.3 功能函数

3.3.1 is_compatible_with_backend_type

  • 不兼容:OSD_MAX7456/OSD_SITL
  • 兼容:OSD_MSP/OSD_MSP_DISPLAYPORT
    bool is_compatible_with_backend_type(AP_OSD::osd_types type) const override {
        switch(type) {
        case AP_OSD::osd_types::OSD_MAX7456:
        case AP_OSD::osd_types::OSD_SITL:
            return false;
        case AP_OSD::osd_types::OSD_NONE:
        case AP_OSD::osd_types::OSD_TXONLY:
        case AP_OSD::osd_types::OSD_MSP:
        case AP_OSD::osd_types::OSD_MSP_DISPLAYPORT:
            return true;
        }
        return false;
    }

3.3.2 get_backend_type

    AP_OSD::osd_types get_backend_type() const override {
        return AP_OSD::osd_types::OSD_SITL;
    }

3.3.3 get_aspect_ratio_correction

无,使用AP_OSD_Backend::get_aspect_ratio_correction

4. 总结

AP_OSD_SITL模拟器上的OSD显示,因此与硬件MAX7456不兼容,与纯软类OSD协议兼容。

5. 参考资料

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

<think>嗯,用户遇到了编译错误,提示找不到mode.h头文件。错误信息显示在HAL_SITL_Class.cpp的第29行,编译过程中断。用户已经确认引用了这个头文件,但编译器还是报错。我需要帮助用户解决这个问题。 首先,我应该考虑常见的导致头文件找不到的原因。可能的情况包括头文件路径没有正确包含、头文件确实不存在、或者文件名大小写不一致。另外,可能涉及到项目配置的问题,比如Makefile或编译脚本的设置。 用户使用的是Waf构建系统,所以需要检查wscript文件是否正确包含了头文件目录。可能HAL_SITL_Class.cpp所在的模块没有正确添加包含路径。或者mode.h可能位于某个子目录中,而路径没有正确指定。 另外,可能mode.h是另一个库的一部分,用户可能忘记安装依赖库,或者依赖库的路径没有正确配置。例如,在ArduPilot项目中,可能存在某些子模块或依赖项需要单独克隆或更新。 还有可能是文件名的大小写问题。例如,头文件实际是Mode.h,而代码中写成了mode.h,这在区分大小写的文件系统(如Linux)上会导致错误。需要用户检查实际文件名的大小写是否正确。 建议用户执行以下步骤: 1. 确认mode.h文件确实存在于项目目录中,使用find命令搜索。 2. 检查头文件包含的路径是否正确,可能需要使用相对路径或绝对路径。 3. 检查wscript文件中是否有正确的include路径设置。 4. 确保所有子模块和依赖项都已正确初始化和更新。 5. 如果文件存在但路径不对,调整#include语句或修改构建配置。 6. 如果问题依旧,查看项目文档或社区是否有类似问题的解决方案。 另外,用户可能在克隆仓库时没有使用--recursive参数,导致子模块缺失。建议用户运行git submodule update --init --recursive来确保所有依赖项都被正确拉取。 如果mode.h是项目新添加的文件,可能需要清理构建目录并重新编译,或者检查文件是否被正确添加到版本控制中。 总结来说,需要从文件存在性、路径配置、构建系统设置、依赖项管理等方面逐一排查。</think>这个编译错误提示表明编译器在编译`HAL_SITL_Class.cpp`时找不到`mode.h`头文件。以下是逐步排查和解决问题的建议: --- ### 1. **确认文件是否存在** 首先检查你的项目目录中是否存在`mode.h`文件: ```bash # 在项目根目录执行搜索(可能需要根据实际情况调整路径) find . -name "mode.h" ``` 如果文件不存在,说明该头文件可能: - 属于未正确克隆的子模块 - 位于非预期的目录 - 文件名大小写不匹配(如实际文件是`Mode.h`) --- ### 2. **检查头文件包含路径** 在代码`#include "mode.h"`中,双引号表示从**当前文件所在目录**开始查找。如果文件实际位于其他目录,需调整路径: ```cpp // 例如,如果 mode.h 在子目录 "include" 中: #include "include/mode.h" ``` --- ### 3. **检查构建系统配置** Waf构建系统依赖`wscript`文件定义编译规则。请确认: - 在`AP_HAL_SITL`模块的`wscript`中是否添加了头文件搜索路径: ```python # 示例:添加包含头文件的目录 obj.uselib = ["AP_HAL_SITL"] obj.includes = ["../../libraries/AP_HAL_SITL/include"] # 假设 mode.h 在此目录 ``` --- ### 4. **验证子模块和依赖项** ArduPilot项目依赖多个子模块。如果`mode.h`属于子模块内容,需确保子模块已初始化: ```bash # 在项目根目录执行 git submodule update --init --recursive ``` --- ### 5. **文件名大小写问题** Linux系统区分文件名大小写。如果实际文件名是`Mode.h`,但代码中写成了`mode.h`,会导致编译失败。手动检查文件系统或使用`ls`命令确认: ```bash ls -l ../../libraries/AP_HAL_SITL/mode.h # 替换为实际路径 ``` --- ### 6. **清理并重新编译** 如果文件路径正确但问题仍然存在,尝试清理构建目录并重新编译: ```bash ./waf distclean ./waf configure --board sitl ./waf ``` --- ### 7. **检查社区或文档** 如果问题仍未解决: - 查阅ArduPilot官方文档中关于SITL编译的说明 - 在GitHub Issues中搜索类似问题(如关键词`AP_HAL_SITL mode.h missing`) - 在ArduPilot开发者论坛提问 --- ### 总结流程图 ```plaintext 报错"mode.h not found" │ ▼ 检查文件是否存在 → 不存在 → 克隆子模块/修复路径 │ ▼ 检查路径大小写 → 不匹配 → 修正#include语句 │ ▼ 检查wscript配置 → 缺失路径 → 添加include目录 │ ▼ 清理并重新编译 → 成功/失败 → 进一步排查依赖或社区支持 ``` 如果问题依旧,建议提供完整的编译日志(添加`-v`参数)以获取更多细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值