江苏省赛-哨兵机器人
嵌入式,机器人,深度学习

RoboMaster江苏省赛哨兵自瞄-视觉电控对接技术经验

背景

RoboMaster江苏省赛于2019年12月20日起在南京理工大学举行。大约在十一月中旬,我们开始着手研究视觉自瞄算法和视觉电控对接调试的工作。而在此前,队伍还从来没有做成过可以自瞄的云台,留下的技术经验也也几乎没有。短短一个月内,全自动运行的哨兵机器人便有了自动瞄准射击敌方机器人的功能,并且在赛场上带来还不错的表现,对此我们十分惊喜。

人员分工

视觉组
  • 吴子昂 视觉算法开发;视觉代码移植;Linux高级玩家(我校linux选修课讲师);大一
  • 王一帆 视觉算法开发;视觉代码移植;大一
  • 赵海鹏 视觉算法开发;视觉代码移植;大一
  • 王景祎 视觉程序开发与移植;上位机串口通信;博主;大一
电控组
  • 王景祎 STM32串口通信;云台PID控制与调试
  • 杨子琦 STM32串口通信;哨兵电控;人在英国刚下飞机远程debug;大三
  • 张申健 哨兵电控;现电控组组长;大三

总览

上面这张图解展现了整个自瞄部分的工作流程。Mini PC固定在云台上作为上位机,在摄像头的画面中寻找敌方装甲板,通过串口发送识别结果。同样在云台的RoboMaster开发板作为下位机,接收数据并通过PID控制装甲板瞄准。

经过多种尝试,整体的控制思路大概是“更多的决策与控制工作都由下位机RM开发板来做,迷你PC和摄像头作为整体,可以看作是下位机的一个传感器。”

视觉部分

省赛最终上场的视觉程序,是基于上海交通大学RoboMaster2019赛季视觉代码加以修改和移植而成的。我们自己也编写了装甲板识别的程序,下文中会提到。但由于备赛时间不足,最终决定移植功能更加成熟的上海交通大学视觉代码参加本次比赛。

上海交通大学自瞄流程图,参见 https://github.com/xinyang-go/SJTU-RM-CV-2019

视觉程序中,首先接收一帧图像,在画面中寻找灯条区域。之后将这些区域按照一些约束条件两两匹配,得到可能是装甲板的区域的候选区域。然后训练好的分类器会对这些可能是装甲板的区域筛选,判断区域内有无数字。如果有数字,则认为这是要击打的装甲板目标,把坐标信息发送给下位机。

如果上述流程成功执行,找到装甲板目标,程序会初始化一个追踪器。对于之后的每一帧图像,程序优先使用追踪器寻找附近的区域并发送目标信息,如果目标丢失,才会重新进入上一段的搜索流程重新寻找目标,以此提升算法效率。

我们使用的上位机为迷你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。感谢您阅读本文,祝您新年快乐!

你可能也会喜欢...