背景
RoboMaster江苏省赛于2019年12月20日起在南京理工大学举行。大约在十一月中旬,我们开始着手研究视觉自瞄算法和视觉电控对接调试的工作。而在此前,队伍还从来没有做成过可以自瞄的云台,留下的技术经验也也几乎没有。短短一个月内,全自动运行的哨兵机器人便有了自动瞄准射击敌方机器人的功能,并且在赛场上带来还不错的表现,对此我们十分惊喜。
人员分工
视觉组
- 吴子昂 视觉算法开发;视觉代码移植;Linux高级玩家(我校linux选修课讲师);大一
- 王一帆 视觉算法开发;视觉代码移植;大一
- 赵海鹏 视觉算法开发;视觉代码移植;大一
- 王景祎 视觉程序开发与移植;上位机串口通信;博主;大一
电控组
- 王景祎 STM32串口通信;云台PID控制与调试
- 杨子琦 STM32串口通信;哨兵电控;人在英国
刚下飞机远程debug;大三 - 张申健 哨兵电控;现电控组组长;大三
总览
上面这张图解展现了整个自瞄部分的工作流程。Mini PC固定在云台上作为上位机,在摄像头的画面中寻找敌方装甲板,通过串口发送识别结果。同样在云台的RoboMaster开发板作为下位机,接收数据并通过PID控制装甲板瞄准。
经过多种尝试,整体的控制思路大概是“更多的决策与控制工作都由下位机RM开发板来做,迷你PC和摄像头作为整体,可以看作是下位机的一个传感器。”
视觉部分
省赛最终上场的视觉程序,是基于上海交通大学RoboMaster2019赛季视觉代码加以修改和移植而成的。我们自己也编写了装甲板识别的程序,下文中会提到。但由于备赛时间不足,最终决定移植功能更加成熟的上海交通大学视觉代码参加本次比赛。
视觉程序中,首先接收一帧图像,在画面中寻找灯条区域。之后将这些区域按照一些约束条件两两匹配,得到可能是装甲板的区域的候选区域。然后训练好的分类器会对这些可能是装甲板的区域筛选,判断区域内有无数字。如果有数字,则认为这是要击打的装甲板目标,把坐标信息发送给下位机。
如果上述流程成功执行,找到装甲板目标,程序会初始化一个追踪器。对于之后的每一帧图像,程序优先使用追踪器寻找附近的区域并发送目标信息,如果目标丢失,才会重新进入上一段的搜索流程重新寻找目标,以此提升算法效率。
我们使用的上位机为迷你PC,CPU为8代i5处理器,操作系统为Ubuntu Server 18.04(没有GUI,相比桌面版也许会快一些)。摄像头为330帧高帧率摄像头。运行环境有OpenCV 3.4.6 (包含Contrib),Eigen3(矩阵运算库),qv4l2摄像头驱动。编译工具为CMake。队员使用的操作系统则为各个发行版的Linux。在开发时,我们使用git工具管理我们的代码,并托管在软件研发管理平台coding.net网站上。
相比上海交通大学的代码,我们做了很多改动,例如去除了原来的摄像头驱动、串口通信相关代码等,增加了读取JSON配置文件的功能,增加了自己的串口代码等。
通过对每秒钟实际发送数据包个数的统计,在搜索目标时帧率可以达到120-150帧左右,找到目标进入追踪模式后,帧率可以达到250帧左右。
通信部分
上位机使用USB-TTL通过串口发送数据,每当处理完一帧图像后,便会发送18个字节的数据。数据包格式示例如下:
如图,第一个字节为起始符,之后的一个字节表示状态——视觉程序是否找到目标。之后的四个字节表示目标在画面中的Y坐标,再四个字节为X坐标——示例中装甲板的中心点在(365.6, 143.5)的位置。之后有若干个预留空间,可以发送目标的大小,距离等更多信息,本次比赛没有使用。最后两个字节为CRC16校验结果。发送端需要根据前16个字节计算并补全,接收端计算并验证。在C语言中可以通过“共用体”union类型方便地把四个字节大的float变量转换为四个uint8_t单字节变量。
下位机RM开发板通过串口DMA接收数据,每当收到一个数据包,中断函数被调用,经过CRC16校验后把字节数据还原为原来的变量,保存在全局变量中。云台控制部分便可以读取这些信息。
尽管下位机向上位机回传数据很有必要,这次省赛中我们没有做这个功能。
云台电控部分
哨兵使用的代码修改自大疆官方步兵开源代码。
云台控制模式
在大疆官方代码中,不同的云台控制模式(gimbal_behaviour_e
)会将云台电机设置为不同的云台电机控制模式(gimbal_motor_mode_e
),并使用不同的方法控制云台的行为。如GIMBAL_ABSOLUTE_ANGLE
表示通过遥控器设置云台的陀螺仪角度来控制云台,GIMBAL_ZERO_FORCE
表示云台无力,把云台电机电流设为0的模式,等。
我们新增了以下三个云台模式:
-
GIMBAL_MOTIONLESS
:云台固定模式,在视觉程序刚丢失目标1秒钟内会进入到此模式。此模式中,会将两个云台电机的模式设置为陀螺仪角度控制模式GIMBAL_MOTOR_GYRO
,并设置云台的陀螺仪角度为刚丢失目标时的,角度的增量始终设置为0。 GIMBAL_CRUISE
:云台巡航模式,视觉程序没有找到目标时进入此模式。 两个云台电机的模式会被设置为陀螺仪角度控制模式GIMBAL_MOTOR_GYRO
,设定的角度以固定的速率增加,以达到云台不停旋转,搜索敌人的目的。GIMBAL_ATTACK
:云台视觉追踪模式,自瞄目标时进入此模式。会设置云台电机模式为视觉PID模式GIMBAL_MOTOR_VISION_PID
(在下文中提到),以视觉程序的结果作为反馈来控制云台对准目标。
最终在gimbal_behaviour.h
文件中,云台控制模式的枚举定义如下:
typedef enum { GIMBAL_ZERO_FORCE = 0, //云台无力 GIMBAL_INIT, //云台初始化 GIMBAL_CALI, //云台校准 GIMBAL_ABSOLUTE_ANGLE, //云台陀螺仪绝对角度控制 GIMBAL_RELATIVE_ANGLE, //云台电机编码值相对角度控制 GIMBAL_MOTIONLESS, //云台固定模式 GIMBAL_CRUISE, //云台巡航模式 GIMBAL_ATTACK, //云台视觉追踪模式 } gimbal_behaviour_e;
云台电机控制模式
在大疆官方代码中,云台电机控制模式(gimbal_motor_mode_e
)会具体控制电机的行为。如云台电机陀螺仪角度控制模式GIMBAL_MOTOR_GYRO
,会通过两层PID控制,实现“控制云台电机达到设定的陀螺仪角度”的功能,即先通过陀螺仪角度环PID,计算要达到某个角度,需要设定的速度。接着通过电机速度环PID,计算要达到这个设定速度,需要最终设定的电机电流值。
云台电机视觉PID模式GIMBAL_MOTOR_VISION_PID
,是我们新增的云台电机模式。该模式下会通过“视觉PID”和“电机速度环PID”两层PID控制来控制云台自瞄,使击打目标的坐标到达画面中心。首先以击打目标与画面中心像素点的偏差作为误差来源,通过视觉PID计算出所需的云台电机速度。之后通过与上文一样的电机速度环PID,计算要达到这个速度需要输出的电流。
测试视频
日期:2019-12-19
如果有任何想法需要交流,或者有任何问题或建议,欢迎与我们交流。您可以直接在评论区回复,或者添加本人微信Jingyi_Wang2000。感谢您阅读本文,祝您新年快乐!