# hnuvision
**Repository Path**: hnuyuelurm/hnuvision
## Basic Information
- **Project Name**: hnuvision
- **Description**: hnuyuelue RoboMaster vision 2023 deploy
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: infantry
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 6
- **Forks**: 0
- **Created**: 2023-05-09
- **Last Updated**: 2025-02-02
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
* [欢迎](#欢迎)
* [程序入口](#程序入口)
* [项目文件目录解释](#项目文件目录解释)
* [自瞄流程](#自瞄流程)
* [标定脚本执行方法](#标定脚本执行方法)
* [程序运行](#程序运行)
* [运行模式](#运行模式)
* [无相机无串口模式](#无相机无串口模式)
* [连接了工业相机但没有串口,并配备装甲板](#连接了工业相机但没有串口并配备装甲板)
* [在车上调试:连接了串口和相机](#在车上调试连接了串口和相机)
* [环境配置](#环境配置)
* [手动切换软件源](#手动切换软件源)
* [安装软件和依赖](#安装软件和依赖)
* [测试程序](#测试程序)
* [设置自启动](#设置自启动)
* [只连接相机时调试方法](#只连接相机时调试方法)
* [串口问题](#串口问题)
* [Bad file descriptor!](#bad-file-descriptor)
* [error sending](#error-sending)
* [2024.1.18](#2024118)
* [识别问题](#识别问题)
* [参数设置](#参数设置)
* [灯条识别正常,但是没有构成装甲板](#灯条识别正常但是没有构成装甲板)
* [解算问题](#解算问题)
* [PnP解算出的相对位置误差较大](#pnp解算出的相对位置误差较大)
* [调试模式](#调试模式)
* [DEBUG_PARAMETERS](#debugparameters)
* [DEBUG_SHOW](#debugshow)
# 欢迎
这里是湖南大学robomaster跃鹿战队视觉运维手册。
作者:徐涵(736946693@qq.com)
# 环境配置
1. 手动切换软件源
直接在系统中切换即可
2. 安装软件和依赖
此处有一键配置脚本,如果其中有的链接失效,可以自行使用搜索引擎下载最新资源。**如果系统语言是中文,有的指令会执行失败。**
```shell
#!/bin/sh
#基础环境配置
sudo apt-get -y upgrade
sudo apt-get -y install git cmake openssh-server libeigen3-dev libopencv-dev
sudo apt-get -y install g++
#下载MVS到~/Download目录,并解压安装
wget -P ~/Downloads/ https://www.hikrobotics.com/cn2/source/support/software/MVS_STD_GML_V2.1.2_231225.zip
unzip ~/Downloads/MVS_STD_GML_V*.zip
sudo dpkg --install ~/Downloads/MVS-2.1.2_x86_64*.deb
#相机驱动文件复制
sudo cp ~/hnuvision/IndustrialCamera/lib/linux/*.so /usr/lib/
sudo cp ~/hnuvision/IndustrialCamera/libs/*.so /usr/lib/
#下载nomachine到/usr目录并解压安装
wget -P ~/Downloads/ https://download.nomachine.com/download/8.11/Linux/nomachine_8.11.3_4_amd64.deb
sudo dpkg --install ~/Downloads/nomachine*amd64.deb
```
3. 修改ip
修改miniPC的ipv4地址如下:
- 手动
- 地址:192.168.1.1
- 掩码:255.255.255.0
- 网关:192.168.1.0
使用nomachine是为了避免每次调试都要连接键鼠。关于组局域网连接nomachine的方法原理的进一步阐释,可以参考[这里](https://blog.csdn.net/qq_50791664/article/details/135578810)。
4. 设置自启动
在启动应用程序中添加
```shell
gnome-terminal -- /home/rm/hnuvision/watchdog.sh
```
5. 串口权限设置
将当前用户加入`dialout`用户组,避免每次都要手动赋予权限。
```shell
sudo usermod -aG dialout rm
```
此外,关于IDE的安装自凭喜好即可。
# 概览
## 主程序
本框架采取多线程的设计思路,在主函数中有四个线程进行工作,如下:
```c++
// 加载参数文件
std::string _config_file_path = argc == 1 ? "../config.yaml" : argv[1];
thread_manager.InitManager(_config_file_path);
// 图像接收线程
std::thread image_acq_thread(&hnurm::ThreadManager::ImageAcquisitionThread, std::ref(thread_manager));
// 图像处理线程
std::thread image_proc_thread(&hnurm::ThreadManager::ImageProcessingThread, std::ref(thread_manager));
// 数据接受线程
std::thread serial_recv_thread(&hnurm::ThreadManager::SerialRecvThread, std::ref(thread_manager));
// 数据发送线程
std::thread serial_send_thread(&hnurm::ThreadManager::SerialSendThread, std::ref(thread_manager));
```
在这四个线程中,图像接收线程负责从相机获取图像,图像处理线程负责对获得的图像提取装甲板目标,预测装甲板的运动状态。数据接受线程负责获取从电控发来的数据,数据发送线程负责将处理后的数据发送到电控。
## 项目文件目录解释
1. Communication: 通信模块,包括串口通信和网络通信。
2. Data: 数据模块,包括装甲板目标的状态信息,线程锁等。
3. IndustrialCamera: 工业相机相关。
4. Logging: 日志模块,包括日志输出和日志文件保存。
5. utils: 工具包,主要是相机的内参等。
6. ThreadManager: 线程管理模块,负责线程的创建和销毁。
7. ArmorDetectorT: 装甲板目标检测模块,包括装甲板目标的检测和识别。
8. Processor: 图像处理和预测模块,目前使用的是PnP结算+拓展卡尔曼滤波进行处理。
9. Cmpensator: 计算弹道,使用迭代方式进行弹道的修正
## 自瞄流程
1. 从相机获取图像,图像接受线程获取图像。
2. 图像处理线程开始进行识别和预测。识别过程不需要接受串口数据,预测需要。识别过程首先计算目标的像素坐标系下的坐标,然后通过PnP算法计算出目标与的相对位置坐标,然后通过预测算法预测出目标对于相机的相对坐标位置、空间位姿、移动速度、半径。
3. 将预测的俯仰角和偏航角发送到串口
# 程序运行模式
## 无相机无串口模式
此情况下,需要一些装甲板的视频文件来输入给图像处理线程,就可以调试图像识别过程了。在config.yaml中输入你的视频路径。
## 连接了工业相机但没有串口,并配备装甲板
此情况下,可以调试图像的识别,可以检验PnP解算出的相对位置是否正确。
- 程序运行方法:
1.不要让程序自动退出,在Serial.cpp中把exit注释掉
```cpp
CLOG(ERROR, "serial") << "Failed to open port!";
//exit(-1);
```
找不到在哪的话,善用IDE的查找功能

2.线程中对接受数据进行自己设置的初始化
```cpp
if (!_recv_buffer.Get(recv, raw_img.time_stamp))
{
//若在个人电脑上进行测试,可以使用默认数据进行初始化
// recv.init();
//若没有收到电控数据,就无法进行预测,直接跳过此次循环,取下一个数据
continue;
}
```
### 在车上调试:连接了串口和相机
# 标定脚本执行方法
1. 准备好标定板,根据标定板的方格数量和方格类型修改`utils/CameraCalibration/default.xml`文件。
```xml
7
7
20
"CIRCLES_GRID"
```
2. `utils/CameraCalibration`中存在CMake文件,编译这个项目并执行,clion中需要指定`Program arguments`为`../default.xml`。在程序执行过程中,按下`G`键开始标定,手持标定板,在图像四个角周围移动标定板。
3. 完成拍摄后,程序会打印出loss(误差值)并自动保存文件,一般认为loss低于0.2是可以接受的。
4. 最后检查一下图像的四周有无肉眼可见的畸变,然后就可以退出程序了。
# 串口问题
## 解包顺序
首先,检查电控发送的俯仰角数据和偏航角数据是否正确对应。惯性传感器坐标系如下:
y==前,z==上,x==右;
y对应roll,z对应yaw,x对应pitch;
右手定则为正方向
如果对应错误,可以在`protocol.cpp`的`encode`和`decode`函数中修改编解码顺序来修正。
## Bad file descriptor!
串口的文件名错误。 下载cutecom调试一下串口。
```shell
sudo install cutecom
```
使用此工具可以查看设备目前所有的串口,找到目前使用的串口的名字,然后在**config.yaml**和**watch.dog**中修改。
找不到在哪的话,善用IDE的查找功能
```yaml
serial:
serial_id: "/dev/ACM0"
```
除此之外,使用cutecom还可以查看串口是否收到数据。
# 装甲板识别问题
## 参数设置
通常是config.yaml中的参数设置不正确。若是识别不出装甲板,重点关注以下参数,目前已经做了滚动条动态调参设计。
```yaml
detector:
min_lightness: 120
light_params:
min_ratio: 0.12
max_ratio: 0.55
max_angle: 40.0
armor_params:
min_light_ratio: 0.6
min_small_center_distance: 0.8
max_small_center_distance: 3
min_large_center_distance: 3.2
max_large_center_distance: 4.5
max_angle: 40.0
classifier_params:
model_path: "../ArmorDetectorT/model/mlp.onnx"
label_path: "../ArmorDetectorT/model/label.txt"
threshold: 0.7
ignore_classes:
- negative
- outpost
- base
- "2"
```
## 灯条识别正常,但是没有构成装甲板
查看config.yaml中ignore_classes参数,可能因为是识别错误被筛除了
```shell
ignore_classes:
- "2"
# - negative
# - outpost
# - base
```
**注意,yaml的格式相当严格,如下格式的yaml无法运行:**
```shell
ignore_classes:
# - negative
# - outpost
# - base
- "2"
```
- 解决数字识别网络的误识别问题:
1. 在适当的距离重新对焦并标定
2. 调整光圈到最大,调整CameraParam.yaml的曝光时间和增益
3. 调整二值化阈值
# 解算问题
## PnP解算出的相对位置误差较大
1. 检查大小装甲板的宽度和高度是否设置正确
```cpp
// 小型护甲的灯条组成矩形的宽度,单位:毫米
static constexpr float SMALL_ARMOR_WIDTH = 135;
// 小型护甲的灯条组成矩形的高度,单位:毫米
static constexpr float SMALL_ARMOR_HEIGHT = 55;
// 大型护甲的灯条组成矩形的宽度,单位:毫米
static constexpr float LARGE_ARMOR_WIDTH = 225;
// 大型护甲的灯条组成矩形的高度,单位:毫米
static constexpr float LARGE_ARMOR_HEIGHT = 55;
```
2. 检查相机成像是否清晰(即焦距是否合适),光圈是否调整到最大。**每次调整完焦距后需要重新标定**。
3. 检查config.yaml中的相机偏移参数是否正确。应该设置为相机光心在机器人坐标系下的坐标:以机器人转轴为坐标原点(问机械组同学),相机镜头方向为y轴正方向,天空为z轴正方向。
```yaml
solver:
calib_info_path: "../utils/CameraCalibration/params/"
camera_bias_z: 0
camera_bias_y: 0
```
5. 检查在装甲板在静止时能否瞄准,并进行开火测试。在以下代码中添加偏移参数以消除物理误差,确保静止目标可以正中靶心。
```cpp
send_data.pitch = pout + bias_pitch;
send_data.yaw = (yout + bias_yaw);
```
# 预测问题
## 查看channel_delay是否设置正确
channel_delay这个时间定义为电控与我们收发信息之间的信道延迟,这个参数会严重的影响预测的准度。这个参数通常难以测得,我们应该把它当做一个超参数来调整,具体而言:
1. 当弹道晚于目标,那么channel_delay过小,程序认为子弹几乎可以立即发射,但现实是子弹发射延迟更大,所以弹道慢了。应该增大channel_delay
2. 弹道早于目标,应该减小channel_delay
## 查看预测角速度是否正确
预测的角速度是能否击中目标的关键,这通常与曝光时间和增益有所关联。曝光时间增加可以获得更多颜色信息,但会降低帧率。
# 调试模式
需要调试时,要在CmakeLists下预定义对应的指令,如:
```cmake
add_compile_definitions(DEBUG_PARAMETERS DEBUG_SHOW)
```
## DEBUG_PARAMETERS
此模式下可以使用滚动条直接调整参数,很方便
## DEBUG_SHOW
创建窗口展示图像和一些参数
# 完整调试流程
1. 光圈最大,对焦并标定(四个角不要有畸变)
2. 根据比赛场地调整曝光和增益,主要是曝光
3. 调整装甲板识别参数、相机光心与惯性传感器的相对位置、摩擦轮中心与惯性传感器的相对位置(在config.yaml中)
4. 静止击打装甲板确保可以正中(调整bias_yaw),如果pitch不准优先调整摩擦系数,最后再设置bias_pitch
5. 反小陀螺调参,主要调延迟时间,要是角速度非常不准就重新适当调整曝光和增益
6. 调整开火策略,决定自瞄发射的速度。
7. 取消所有调试窗口,注释掉cmakelists文件中类似`#define DEBUG_PARAMETERS`的预定义,确保性能