此仓库仅作为本人在RoboMaster创梦之翼的工作记录,包含能量机关的识别和预测,本套代码理论上应在创梦之翼自瞄的基础上运行,但由于自瞄代码属于战队内部资源,不应该在个人仓库中公开,因此本套代码不保证能运行,仅作记录。
务必认真阅读完规则手册后再阅读以下内容
不含自瞄
- 扇叶:代码中描述扇叶的变量名一般为
fanblade
,如下图蓝色框框选处,共五片。
- R 型标:代码中描述R型标的变量名一般为
R
,如下图,一般位于能量机关装置的中心凸起处。
- 流水灯:代码中描述流水灯的结构体名为
WaterfallLight
,如下图黄色箭头所指处。
- 月牙形框:代码中描述月牙形框架的结构体名为
MoonFrame
,如下图蓝色框圈出的区域所示;其中月牙形框又分为outside_moon
和inside_moon
,顾名思义外月牙就是距离 R 标远的,内月牙就是距离 R 标近的,下图所示上蓝框为外月牙、下蓝框为内月牙。(注:历史原因,在调试图像上,Moon 即为 outside_moon,T 即为 inside_moon)
Fanblade.msg
std_msgs/Header header
geometry_msgs/Pose fanblade_center //扇叶中心坐标
geometry_msgs/Pose r_center //能量机关中心R型标坐标
geometry_msgs/Pose quaternion
float64[3] t_vec
uint8 rotation 0 //能量机关转向,默认为零,1顺2逆
Target.msg
std_msgs/Header header
geometry_msgs/Pose pose //待击打目标点位姿
float64 angle //当前扇叶角度
bool is_tracked
TrackedRune.msg
std_msgs/Header header
TargetState target_state
bool is_tracked
recognition-node
:接受从相机节点中发来的/camera/front/capture
、/camera/front/camera_info
进行图像处理识别,经过一系列函数preprocess
、findWaterfallLight
、findMoonFrame
、matchFanBlade
、solvepnp
,构建Fanblade
消息以/rune/fanblade
发送出去transform-node
:将接收到的相机系下的坐标转换为惯性系下prediction-node
:进行大小符预测,解算出惯性系下待击打目标点,构建Target
消息发送出去tracker-node
:将待击打的目标点套一层匀速卡尔曼滤波,使其更加平滑,减少云台抖动。该节点滤波器部分主要是@花譜所写。
只做概述,细节见代码
整体识别逻辑代码中较为清晰,此处不做赘述,但有几处判断逻辑需要额外说明一下:
- 颜色判断:取流水灯区域为 ROI,进行通道分离,根据红蓝通道均值大小判断颜色,红色通道均值大于蓝的为红,反之为蓝,详见代码;
- 内外月牙框的判断:遍历所有月牙形框,取与流水灯在一条直线上的两个框,距离流水灯近者为内月牙框,远的则为外月牙形框,详见代码;
- 能量机关转向的判断:记录前后两帧内外月牙框中心坐标,记内月牙框中心到外月牙框中心的向量为
v
,利用前后两帧向量的叉乘的正负判断顺逆时针旋转,详见代码; - pnp 取点逻辑:计算方法使用
cv::SOLVEPNP_IPPE
,图像上的四点位置及顺序见下图。具体的选点方法也是根据向量叉乘结果的正负号判断的,代码已足够清楚,这里不再赘述。
需要注意的是识别使用了两套参数:reco_config.yaml
和reco_home_test.yaml
,前者为赛场光照环境下识别官方能量机关的参数,后者为家里场地光照环境下识别参数,在launch
中可以切换。
只做概述,细节见代码
预测部分除模型外唯一需要说明的就是模型求解之前的数据处理,由于两帧之间的时间差过于小,直接算角速度就会有较大的误差,因为这里的时间数量级很小,一个微小的误差会被无限放大,导致解算出的角速度误差很大,为避免这种情况,代码中直接使用角度和时间这两个自变量求解模型。代码中的数据处理部分目标在于创建一个从零开始的、具有目标长度的序列,利用这两个序列求解模型。代码已足够明了。
对于模型部分,代码实现了GD(梯度下降法)、Ceres(google的一个开源 C++ 库,用于建模和解决大型、复杂的优化问题)以及高斯牛顿法。具体步骤可参考链接,不过实测下来Ceres和高斯牛顿法效果不佳,建议换更好的模型,可以参考一下这个GitHub - FaterYU/rm_buff: RoboMaster buff detect and predict,感觉不错。
识别添加了在调试图像中的错误参数显示,在轮廓面积参数通过的情况下,对于错误识别的物体会以白色将其轮廓画出,并将参数错误值标注在轮廓旁边,具体如下图所示(这里显示的是未通过的MoonFrame
的asp
参数实际值,画出的白色轮廓有些不明显,但放大还是可以看到的),然后根据显示的实际值调整相关参数,参考下面的调试视频(软件为 Foxglove,可以与ROS2联动,实现实时调参、实时更改)。
- 预测模型收敛准确度不高,赛场上临时改用了一种极为狗屎的方法,详见代码。建议直接换模型;
tracker
节点匀速模型滤波有问题:滤波出的坐标与实际坐标有微小偏移,如图,这导致实际击打时需要给予 yaw, pitch 一定量的偏移,在自瞄firecontrol
节点中专门加了关于能量机关的偏移补偿。
- 预测模型改进:高斯牛顿法和梯度下降法收敛速度较慢且预测准确度不高,可以尝试对能量机关使用拓展卡尔曼滤波进行整体建模,参考GitHub - FaterYU/rm_buff: RoboMaster buff detect and predict;
tracker
节点滤波器改进:目前tracker
中采用的匀速模型卡尔曼滤波不太可靠,需要探索出更适合能量机关的、专用的模型;- 自动击打:目前小符的命中率接近100%,可以尝试改用自动击打。大符在保证手动击打具有较高准确率的情况下,也可以尝试自动击打;
- 神经网络识别:预测准确度较高、击打效果较好的情况下,可以考虑将识别换成神经网络。
- 一些建议:强烈建议优先优化预测模型和滤波器。如果官方不对能量机关整体形状做大的改变的话,识别可以不用改动,把更多的时间放在预测模型的优化上;在保证预测准确度较高的情况下再尝试神经网络识别。
- 调试视频也已上传至语雀视觉组资源处,在 ROSbag 文件夹中