readme增加module单独测试用例,增加工程和平衡步兵展示gif

This commit is contained in:
NeoZng 2023-07-26 22:13:58 +08:00
parent cb3aeb4063
commit ce90b3852c
3 changed files with 69 additions and 18 deletions

BIN
.assets/balance.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 MiB

BIN
.assets/engineering.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 MiB

View File

@ -37,11 +37,23 @@
## 功能介绍和展示
这是湖南大学RoboMaster跃鹿战队电控组2022-2023赛季的通用嵌入式控制框架可用于**机器人主控**、自研模组imu/测距等各种传感器、超级电容控制器等。该框架旨在打造上手简单、易于移植、高代码复用、层级分明、结构清晰的一套SDK供队内使用&RM参赛队伍&嵌入式开发者交流学习。
### 起源
通过精心设计的bsp和module支持以及成熟的app示例该框架可以在短时间内为不同类型和结构的机器人轻松构建电控程序可扩展性和可维护性相较目前的大部分开源代码和本队的老代码提升巨大
这是湖南大学RoboMaster跃鹿战队电控组2022-2023赛季的通用嵌入式控制框架可用于**机器人主控**、自研模组imu/测距等各种传感器)、超级电容控制器等
同时相较于传统的基于KEIL MDK开发的工作流我们提供了基于arm-gnu工具链+VSCode/Clion+Ozone&Systemviewer/FreeMaster的现代化开发工作流你再也不用面对上个世纪的UI忍受没有补全和高亮的代码了在配套现代化开发工具支持下将极大提高电控开发效率和调试效率。硬件模块测试和整车联调从未如此简单
从目前的RoboMaster开源社区来看大部分队伍都没有一套规则统一符合较大规模软件开发原则的框架有些学校连不同兵种代码都相去甚远甚至连队伍用于传承的代码注释都寥寥无几全靠师傅带徒弟言传身教。当然不乏有广东工业大学DynamicX开源的rm_control这样规范且先进的系统但基于Linux、ROS、C++的这套软件栈对于新人来说还是过于复杂(但我们很推荐熟悉基本工具的同学使用!)。
### 优势
为此basic_framework应运而生。该框架旨在打造上手简单、易于移植、高代码复用、层级分明、结构清晰的一套SDK供队内使用&RM参赛队伍&嵌入式开发者交流学习。通过精心设计的bsp和module支持以及成熟的app示例该框架可以在短时间内为不同类型和结构的机器人**轻松构建**电控程序,**可扩展性**和**可维护性**相较目前的大部分开源代码和本队的老代码提升巨大。
同时相较于传统的基于KEIL MDK开发的工作流我们推出了基于arm-gnu工具链+VSCode/Clion+Ozone&Systemviewer/FreeMaster的**现代化开发工作流**和非**常完善配套教程**你再也不用面对上个世纪的UI忍受没有补全和高亮的代码了在现代化开发工具支持下将**极大提高电控开发效率和调试效率**。硬件模块测试和整车联调从未**如此简单方便**
> 用软件开发的思想设计嵌入式系统是一种降维打击
>
> <p align=right>—— 沃兹基·烁德</p>
### 效果展示
![](.assets/allrobot.jpg)
@ -56,8 +68,24 @@
<center>展示中的视觉识别与预测算法是基于rm_vision打造的</center>
3. 工程机器人流程化抓取矿石/兑换矿石/救援’
![engineering](.assets/engineering.gif)
4. 平衡步兵机器人
![balance](.assets/balance.gif)
这些机器人的程序均基于basic_framework打造已在我们的仓库中提供[HNUYueLuRM](https://gitee.com/hnuyuelurm)
> 更多测试视频可以关注我们的bilibili账号[湖南大学跃鹿战队](https://space.bilibili.com/522795884)或在bilibili搜索跃鹿战队观看我们的比赛视频。
---
## 架构
总览。
@ -70,31 +98,41 @@
### 设计思想
框架在结构上分为三层bsp/module/app。整体使用的设计模式是**结构层级模式**,即每个“类”包含需要使用的底层“类”,通过组装不同的基础模实现更强大的功能而最顶层的app之间则通过**pub-sub消息机制**进行解耦,使得在编写代码时不会出现相互包含的情况。
1. ***首先,总览框架的设计模式。***
**pub-sub机制的体现**以本仓库的app层为例包含了chassisgimbalshootcmd四个应用每个应用都对应了机器人上的不同模组。cmd应用负责从机器人控制信号来源遥控器/上位机/环境传感器)处获取信息并解析成各个**执行单元的实际动作**(电机/舵机/气缸/阀门等的扭矩/速度/位置/角度/开度等),并将此信息**发布**出去。chassis、gimbal、shoot等包含了执行单元的应用则**订阅**这些消息,并通过自己包含的子模块,调用它们的接口实现动作
框架在结构上分为三层bsp/module/app。整体使用的设计模式是**结构层级模式**即每个“类”包含需要使用的底层“类”通过组装不同的基础模实现更强大的功能。而最顶层的app之间则通过**pub-sub消息机制**进行解耦,使得在编写代码时不会出现相互包含的情况
**结构层级模式的体现**以chassis应用为例chassis中包含了4个底盘电机模块。当chassis收到cmd应用的信息希望让底盘以1m/s的速度前进。chassis首先根据底盘的类型舵轮/麦克纳姆轮/全向轮/平衡底盘)以及对应的动力学/运动学解算函数计算得到每个电机的输目标输入值此时chassis将输入通过电机模块motor module的接口将设定值告知电机。而每个电机模块又有各自的PID计算模块和自身电流&速度&角度传感器的信息可以计算出最终需要的电流设定值。假设该电机使用CAN协议与电调通信则电机通过自身包含的CANInstancebsp_can提供用于和实际硬件交互电机模块将设定值电流值或其他指令按照通信协议组织在CAN报文中通过CANInstance提供的接口把最终控制数据发送给电调实现控制闭环。可以看到**包含关系为chassis∈motor∈bspcan**。
我们希望通过bsp对硬件的抽象使得module的编写更为轻松不需要考虑底层的硬件具体是如何运作的再通过module的外接模块的抽象使得app的编写可以通过完全硬件无关的方式考虑达到*”只阅读module的说明文档就能迅速开发应用 ”*的程度。bsp和module的设计愿景就是成为人们常说的***中间件**。*
有了上面的大体认知,我们分别介绍框架的三层结构
**pub-sub机制的体现**以本仓库的app层为例包含了chassisgimbalshootcmd四个应用每个应用都对应了机器人上的不同模组。cmd应用负责从机器人控制信号来源遥控器/上位机/环境传感器)处获取信息并解析成各个**执行单元的实际动作**(电机/舵机/气缸/阀门等的扭矩/速度/位置/角度/开度等),并将此信息**发布**出去。chassis、gimbal、shoot等包含了执行单元的应用则**订阅**这些消息,并通过自己包含的子模块,调用它们的接口实现动作
- **bsp**即板级支持包提供对开发板外设的软件抽象让module层能使用和硬件无关的接口由bsp提供进行数据处理与交互。bsp层和ST的HAL为强耦合与硬件直接绑定。若要向其他的ST芯片移植基本不需要修改bsp层若是其他单片机则建议保留**接口设计**,对接口调用进行重现实现。每一种外设的头文件中都定义了一个**XXXInstance**xxx为外设名其中包含了使用该外设所需要的所有数据如发送/接收的数据长度id如果有父指针指向module实例的指针用于回调等。由于C没有`class`因此所有bsp的接口都需要传入一个额外的参数XXXInstance*用于实现c++的`this`指针以区分具体是哪一个实例调用了接口
**结构层级模式的体现**以chassis应用为例chassis中包含了4个底盘电机模块。当chassis收到cmd应用的信息希望让底盘以1m/s的速度前进。chassis首先根据底盘的类型舵轮/麦克纳姆轮/全向轮/平衡底盘)以及对应的动力学/运动学解算函数计算得到每个电机的输目标输入值此时chassis将输入通过电机模块motor module的接口将设定值告知电机。而每个电机模块又有各自的PID计算模块和自身电流&速度&角度传感器的信息可以计算出最终需要的电流设定值。假设该电机使用CAN协议与电调通信则电机通过自身包含的CANInstancebsp_can提供用于和实际硬件交互电机模块将设定值电流值或其他指令按照通信协议组织在CAN报文中通过CANInstance提供的接口把最终控制数据发送给电调实现控制闭环。从调用来看三个层级的**包含关系为chassis∈motor∈bspcan**
- **module**即模块层,包括了需要开发板硬件外设支持的(一般用于通信)真实**硬件模组**如电机、舵机、imu、测距传感器和通过软件实现的**算法**如PID、滤波器、状态观测器还有用于兼容不同控制信息模块遥控器/ps手柄/图传链路/上位机的统一接口模块以及为app层提供数据交互的message center。
2. ***有了上面的大体认知,我们分别介绍框架的三层结构。***
module层仍然是基于实例的一个app会包含多个module的instance。当app便可以用硬件无关的接口使用module如要求电机以一定速度运动、关闭气阀、给超级电容或上位机发送一些反馈数据等。在有了方便的bsp之后只需要在你构建的module中包含必须的bsp然后为app提供合理的接口即可
- **bsp**即板级支持包提供对开发板外设的软件抽象让module层能使用和硬件无关的接口由bsp提供进行数据处理与交互
- **app**是框架层级中最高的部分。目前的框架设计里会有多个app任务运行在freertos中当然你也可以根据需要启动一些事件驱动的任务所有的任务安排都放在`app/robot_task`中。当前的app层仅是一个机器人开发的示例有了封装程度极高的module你可以在app完成任何事情。
bsp层和ST的HAL为强耦合与硬件直接绑定。若要向其他的ST芯片移植基本不需要修改bsp层若是其他单片机则建议保留**接口设计**,对接口调用进行重现实现。每一种外设的头文件中都定义了一个**XXXInstance**xxx为外设名其中包含了使用该外设所需要的所有数据如发送/接收的数据长度id如果有父指针指向module实例的指针用于回调等。由于C没有`class`因此所有bsp的接口都需要传入一个额外的参数XXXInstance*用于实现c++的`this`指针以区分具体是哪一个实例调用了接口。
- **module**即模块层,包括了需要开发板硬件外设支持的(一般用于通信)真实**硬件模组**如电机、舵机、imu、测距传感器和通过软件实现的**算法**如PID、滤波器、状态观测器还有用于兼容不同控制信息模块遥控器/ps手柄/图传链路/上位机的统一接口模块以及为app层提供数据交互的message center。
module层仍然是基于实例的一个app会包含多个module的instance。当app便可以用硬件无关的接口使用module如要求电机以一定速度运动、关闭气阀、给超级电容或上位机发送一些反馈数据等。在有了方便的bsp之后只需要在你构建的module中包含必须的bsp然后为app提供合理易用的接口即可。
- **app**是框架层级中最高的部分。目前的框架设计里会有多个app任务运行在freertos中当然你也可以根据需要启动一些事件驱动的任务所有的任务安排都放在`app/robot_task`中。当前的app层仅是一个机器人开发的示例有了封装程度极高的module你可以在app完成任何事情。
目前的app设计里可以兼容多块开发板的情况通过**条件编译**切换开发板的位置。如步兵机器人可以将主控MCU放在云台上而超级电容控制板同时作为底盘板。使用CAN/SPI/UART将两者连接便可以通过**`app/robot_def.h`**中的宏完成设置。可以根据需要,设置更多的开发板(双云台哨兵、工程机器人)。
这套框架可以轻松扩展到所有机器人上在我们的仓库中有步兵机器人、平衡步兵机器人、哨兵机器人、英雄机器人、工程机器人以及空中机器人的代码实例皆按照本框架中的三层结构开发。若设计了新的机器人只需要在robot_def.h中修改传感器的位置、底盘轮距轴距、拨弹盘容量、弹舱载弹量等参数便可以**立刻实现部署**。
至于bsp和module中每个instance的设计我们采用了**面向对象**的C风格代码整个框架也统一了变量和函数命名方式调用层级和数据流十分清晰下一个章节也有插图阐述
3. ***知道了每个层级的结构之后,我们再谈谈如何进行每层的开发。***
为了避免出现”底层代码包含上层头文件“的情况我们让bsp层instance在注册时要求module提供数据发送/接收的回调函数指针从而在发生对应中断或事件时完成对module函数的”反向调用“。事实上你也可以进一步将这套思想放入app的设计中当某个事件发生时触发app的任务而不是将app的任务定时运行这可以提高运行效率降低cpu占用)。
对于bsp和module中每个instance的设计我们采用了**面向对象**的C风格代码整个框架也统一了变量和函数命名方式调用层级和数据流十分清晰下一个章节也有插图阐述)。
bsp和module的instance在初始化时接口皆为**`XXXInstance* XXXRegister(XXX_Init_Config_s* conf)`**传入该实例所需的config参数返回一个实例指针看作this指针之后要调用模块的功能传入该指针即可。我们还提供了守护线程以供module选用当异常情况发生时在LOG中发送warning、触发蜂鸣器或LED进行声光报警以及错误/离线回调函数,保证系统的鲁棒性和安全性。
为了避免出现”底层代码包含上层头文件“的情况我们让bsp层instance在注册时要求module提供数据发送/接收的回调函数指针从而在发生对应中断或事件时完成对module函数的”反向调用“。事实上你也可以进一步将这套思想放入app的设计中当某个事件发生时触发app的任务而不是将app的任务定时运行这可以提高运行效率降低cpu占用
bsp和module的instance在初始化时接口皆为**`XXXInstance* XXXRegister(XXX_Init_Config_s* conf)`**传入该实例所需的config参数返回一个实例指针看作this指针之后要调用模块的功能传入该指针即可。我们还提供了守护线程以供module选用当异常情况发生时在LOG中发送warning、触发蜂鸣器或LED进行声光报警以及错误/离线回调函数,保证系统的鲁棒性和安全性。
而对于app的开发由于底层接口已经设计的较为完善不同的机器人可以直接**`fork`** basic_framework的代码开发app层。当bsp和module有功能更新时只需要通过git的cherry-pick-commit功能将更新拉取到自己的仓库**获得动态的热更新而无需手动合并分支!**
@ -180,7 +218,7 @@ app、module和bsp都有相应的rtos任务。其中bsp为创建任务提供了
随后通过调试器将开发板连接至你的电脑点击上方tab页的终端terminal->运行任务run task)选择download_dap or download_jlink或你自己编写的stlink/ulink/...便会开始下载终端或jFlash中会提示擦除、下载、验证的进度。
想要调试在左侧tab页选择合适的调试选项按F5或图形界面的绿色小三角形按钮开始调试。
想要调试在左侧tab页选择合适的调试选项按F5或图形界面的绿色小三角形按钮开始调试。当然调试器的设置也请参考配置文档主要是将可执行文件路劲加入环境变量的PATH。
**更详细的开发流程,请参照`.Doc/VSCode+Ozone使用方法.md`**
@ -192,7 +230,7 @@ app、module和bsp都有相应的rtos任务。其中bsp为创建任务提供了
- [Bug_Report](.Doc/Bug_Report.md) 提供了一些提交issues的模板范例若在使用中出现问题请按照模板提供信息。
- [TODO](.Doc/TODO.md) :框架后续开发计划和维护说明
- **[VSCode+Ozone使用方法.md](VSCode+Ozone使用方法.md)** **重要**上手必看。介绍了当前开发工作流和传统KEIL开发的不同先讲解一些与工具链有关的基础知识然后说明了如何配置开发环境安装必要的软件和一些”操作“。还涉及了VSCode编辑调试和Ozone示波器&trace功能的使用指南。
- **[VSCode+Ozone使用方法](.Doc/VSCode+Ozone使用方法.md)** **重要**上手必看。介绍了当前开发工作流和传统KEIL开发的不同先讲解一些与工具链有关的基础知识然后说明了如何配置开发环境安装必要的软件和一些”操作“。还涉及了VSCode编辑调试和Ozone示波器&trace功能的使用指南。
- [合理地进行PID参数整定](.Doc/合理地进行PID参数整定.md) 介绍了如何为PID控制器进行参数整定包括简单的经验准则和基于模型的前馈控制、扰动消除等方法。
- [如何定位bug](.Doc/如何定位bug.md) 当嵌入式开发出现bug时以更高效地方法进行错误定位和复现。简单的调试器使用技巧。
- [必须做&禁止做](.Doc/必须做&禁止做.md) :字如其名
@ -205,6 +243,19 @@ app、module和bsp都有相应的rtos任务。其中bsp为创建任务提供了
建议以自上而下的方式阅读代码app-》module-》bsp我们还提供了框架的说明视频分别讲解每个抽象层和总体的设计思路还有一些杂碎的开发相关知识[basic_framework教程]()
### 运行单个bsp/module测试
**每个bsp和module的文件夹中都有各自的说明文档**,测试用例和使用方法都在文档中给出,非常方便。
想要进行硬件查错、连线检查或测试,如测试开发板功能(外设)是否完好,电机电调能否正常使用,或给新人提供教学,只要:
1. 将main.c中的`RoboInit()`函数删除,然后包含`bsp_init.h`头文件,在原`RoboInit()`的位置添加一个`BSPInit()`
2. 包含用于测试的bsp或module头文件根据说明文档的用例初始化对应的支持包或模块即可。
3. 同时可以将实时系统的初始化注释或删除,在`main.c`的`while(1)`主循环中进行测试,也可以使用`bsp_tim.h`提供的定时任务。
4. 编译,下载,运行,调试。
我们为机械和视觉的同学能方便测试硬件模块的好坏,设计了一套通过串口和遥控器控制的**硬件功能测试程序**,使得其他技术组成员可以操作这个”黑箱“,在没有电控组成员的时候也不会卡住其他队员的进度。
### VSCode集成工具
我们在`.vscode`下提供了编写好的一些任务包括编译烧录启动RTT终端LOG启动Ozone调试等。有些功能需要配置vscode的插件设置或将一些可执行文件加入环境变量这些步骤已经在[VSCode+Ozone使用方法.md](.Doc/VSCode+Ozone使用方法.md)中给出;`launch.json`里包含了最常见的四种调试任务使用jlink-server/openocd启动或附加调试。