码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • PX4模块设计之十七:ModuleBase模块


    PX4模块设计之十七:ModuleBase模块

    • 1. ModuleBase模块介绍
    • 2. ModuleBase类介绍
    • 3. ModuleBase类功能介绍
      • 3.1 模块入口
      • 3.2 模块启动
      • 3.3 模块停止
      • 3.4 状态查询
      • 3.5 任务回调
      • 3.6 辅助函数
    • 4. 总结
    • 5. 参考资料

    1. ModuleBase模块介绍

    ModuleBase模块是一个基础类,主要完成各个模块需要的基础功能,比如:start, stop, status命令,但是目前尚不支持多实例(类似mavlink模块多实例应用)。

    当继承自该类的模块:

    • 必须完成以下函数实现:
    1. static int task_spawn(int argc, char *argv[])
    2. static T *instantiate(int argc, char *argv[])
    3. static int custom_command(int argc, char *argv[])
    4. static int print_usage(const char *reason = nullptr)
    • 根据情况重构以下函数实现:
    1. virtual int print_status()
    2. virtual void run()
    3. virtual void request_stop()

    2. ModuleBase类介绍

    这是一个UML绘图工具绘制的ModuleBase类定义(给出一个整体的picture)。

    ModuleBase类 UML图
    注:由于PX4的代码已经都完成了实现,从代码上逆向回来的UML图,所以感觉很细(很具体化);设计上的一些内容(注释,考虑,场景分析等)看不太出来。如果自上而下的UML设计,会注意到有非常多的描述。这里只是用了UML画个图,做个整体的了解。知道这个类有哪些函数、参量,以及public/protected/private属性。所以不再去考虑和分析设计这个类的时候设计人员的想法(也无从得知)。

    3. ModuleBase类功能介绍

    3.1 模块入口

    ModuleBase::main
     ├──> 
     │   └──> return T::print_usage();                                //【必须实现】的函数
     ├──> <命令参数 "start">
     │   └──> return start_command_base(argc - 1, argv + 1);
     ├──> <命令参数 "status">
     │   └──> return status_command();
     ├──> <命令参数 "stop">
     │   └──> return stop_command();
     ├──> lock_module(); // Lock here, as the method could access _object.
     ├──> int ret = T::custom_command(argc - 1, argv + 1);            //【必须实现】的函数
     └──> unlock_module();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在PX4飞控系统代码中模块入口采用的是_main来作为app应用入口的。这里只是ModuleBase::main,在实际符号链接之前要做转换。我们以logger模块为例:

    int logger_main(int argc, char *argv[])
    {
    	// logger currently assumes little endian
    	int num = 1;
    
    	if (*(char *)&num != 1) {
    		PX4_ERR("Logger only works on little endian!\n");
    		return 1;
    	}
    
    	return Logger::main(argc, argv);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    此时logger_main是logger模块的应用入口,然后【PX4模块设计之十一:Built-In框架】通过CMakelist将logger模块的应用入口编译和链接到系统中。

    注:main的写法与【Linux应用程序之Helloworld入门】里面的入口main一致,符合常规习惯。

    3.2 模块启动

    检查是否已在运行,如果尚未运行,则调用T::task_spawn()。

    ModuleBase::start_command_base
     ├──> lock_module();
     ├──> 
     │   └──> PX4_ERR("Task already running");
     ├──> 
     │   └──> ret = T::task_spawn(argc, argv);                    //【必须实现】的函数
     └──> unlock_module();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.3 模块停止

    检查模块是否正在运行,如果正在运行,则请求模块停止并等待任务完成。

    ModuleBase::stop_command
     ├──> lock_module();
     ├──> 
     │   ├──> T *object = _object.load();
     │   ├──> 
     │   │   ├──> object->request_stop();  // 发布stop应用指令
     │   │   └──> do {} while (_task_id != -1);
     │   │       ├──> unlock_module();
     │   │       ├──> px4_usleep(10000); // 10 ms, 定期循环查询_task_id是否==-1(满足条件表明模块自己已经优雅退出)
     │   │       ├──> lock_module();
     │   │       └──> <++i > 500 && _task_id != -1>  // wait at most 5 sec
     │   │           ├──> PX4_ERR("timeout, forcing stop");
     │   │           ├──> <_task_id != task_id_is_work_queue>  // 如果已经创建task,需要强制删除任务
     │   │           │   └──> px4_task_delete(_task_id);
     │   │           ├──> _task_id = -1;
     │   │           ├──> delete _object.load();
     │   │           ├──> _object.store(nullptr);
     │   │           └──> break
     │   └──> 
     │       └──> _task_id = -1;
     └──> unlock_module();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3.4 状态查询

    检查是否正在运行,如果正在运行,则调用print_status()。

    ModuleBase::status_command
     ├──> lock_module();
     ├──> 
     │   ├──> T *object = _object.load();
     │   └──> ret = object->print_status();
     ├──> 
     │   └──> PX4_ERR("failed to instantiate object");
     └──> unlock_module();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.5 任务回调

    创建任务以后,ModuleBase通过px4_task_spawn_cmd封装了任务入口函数run_trampoline。

    ModuleBase::run_trampoline
     ├──> T *object = T::instantiate(argc, argv);                //【必须实现】的函数
     ├──> _object.store(object);
     ├──> 
     │   └──> object->run();
     ├──> 
     │   └──> PX4_ERR("failed to instantiate object");
     └──> exit_and_cleanup
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.6 辅助函数

    static bool is_running()                                       //判断模块是否已经启动
    bool should_exit()                                             //判断模块是否需要退出
    static void exit_and_cleanup()                                 //清除当前模块对象(清空指针)
    static int wait_until_running(int timeout_ms = 1000)           //等待实例初始化完成,可以在task_spawn最初阶段
    static T *get_instance()                                       // 获取当前模块实例
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4. 总结

    ModuleBase类总体上看类似一个简单封装,将模块设计的基本框架搭建好了,完成最为基本的start/stop/status功能。关于具体是否创建任务(线程),还是使用工作队列,ModuleBase类都没有具体给出。

    关于模块是否采用任务(T::task_spawn内部实现),还是采用WorkQueue(继承WorkItem实现),在后续章节中再做深入。

    5. 参考资料

    【1】PX4开源软件框架简明简介
    【2】Linux应用程序之Helloworld入门
    【3】PX4模块设计之十一:Built-In框架
    【4】PX4模块设计之十三:WorkQueue设计

  • 相关阅读:
    想要一个漂亮的博客?Simple Memory - 博客园 cnblogs 个性化博客配置
    Yii2 ActiveRecord连接OpenGauss提示表不存在table not exist
    GIT常用操作记录
    基于jeecgboot的flowable增加流程节点抄送功能
    【性能测试入门必看】性能测试理论知识
    什么是文件包含漏洞?文件包含漏洞分类!
    yum安装mysql8
    深度学习之AlexNet、VGG-19、VGG-16、LeNet-5、ResNet模型的训练
    电脑分辨率怎么调?电脑分辨率怎么调合适
    设计模式-21状态模式(状态设计模式)详解
  • 原文地址:https://blog.csdn.net/lida2003/article/details/126173134
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号