# 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的查找功能 ![](assets/Screenshot from 2024-01-16 02-22-45.png) 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`的预定义,确保性能