Skip to content

视觉组笔试题

4232字约14分钟

2025-09-08

RoboMaster视觉组招新测试题(难)

致机器人爱好者:

你好!欢迎来到RoboMaster视觉组核心队员的招新测试。

这份测试旨在全面评估你的工程实践能力、算法设计思想以及对机器人视觉领域的理解。我们期望你不仅能实现功能,更能展现出代码的健壮性、结构性以及对技术细节的深入思考。

请将所有任务的解决方案保存在一个私有的Git仓库中。我们高度重视你的README.md文档,它应清晰地阐述你的设计决策、实现方法和遇到的挑战。完成后,请将仓库访问权限分享给负责的学长学姐。(仓库地址请在填写申请表单时写上去)

注意:

  • 对于AI的使用我们不做限制,但是我们希望看到你的代码风格。

  • 我们同时也不强求你能做完所有题目,尽力而为!如果编程题目未能完成,也需要写出你的思路与伪代码。

核心考核要求:统一的测试与验证方式

为了保证评估的公平和高效,我们要求所有编程任务都提供一个统一的、自动化的测试方式。

  • 对于每个编程任务,你必须提供一个 test.sh 脚本,或是一个带有 test 目标的 Makefile
  • 这个脚本/目标的功能是完整地编译、运行并验证你的代码。
  • 对于库类型的代码(如C++类),我们鼓励你编写一个独立的 test.cpp 文件来调用和展示其功能。
  • 学长学姐在评估时,会直接进入每个任务的文件夹,执行 bash test.shmake test 来验证你方案的正确性。
  • 对于Python环境管理,我们希望你可以使用一些包管理器(uv,conda)。

期待看到你卓越的工程作品。


第一部分:理论理解题

背景: 我们期望你对技术方案有深入的理解和批判性思维。

任务: 请仔细阅读《了解CV和RoboMaster视觉组》文档,并根据你的理解回答以下问题(请将答案写在task1_theory/README.md中):

  1. 文档分别介绍了传统的灯条匹配方法基于CNN的目标检测方法来识别装甲板。

    请结合文档内容,从鲁棒性、实时性、开发成本、可维护性四个维度,对比这两种技术路线的优缺点。

  2. 文档中多次提到了卡尔曼滤波器(Kalman Filter)

    请阐述为什么在进行目标运动预测时,需要使用卡尔曼滤波器这类工具,而不是简单地用两帧之间的位置差来计算速度?它在机器人运动预测任务中主要解决了什么问题?

  3. 文档在介绍 Focal Loss 时提到,one-stage检测器面临着严重的正负样本不均衡问题。

请解释什么是正负样本不均衡,以及为什么它会对模型的训练产生负面影响?Focal Loss是如何通过修改损失函数来缓解这个问题的?

  1. 文档深入探讨了CNN是否具有平移不变性 (Translation Invariance)

    请总结一下,为什么说池化层(Pooling)和步长不为1的卷积(Strided Convolution)是破坏CNN平移同变性(Equivariance)的主要原因?

  2. solvePnP是视觉组进行位姿估计的核心函数之一。

    请阐述:1) solvePnP函数的主要作用是什么? 2) 为了成功调用它,除了2D图像上的目标角点坐标外,我们还必须提供哪些关键的先验信息?


第二部分:工作站环境配置与部署

背景: 任何复杂的机器人软件都始于一个稳定、可复现的开发环境。

任务:

  1. 开发环境自动化: 编写一个 setup_env.sh Bash脚本,用于自动化安装机器人开发所需的核心工具集:git, cmake, docker.io等等。脚本需妥善处理相关用户权限,以及不同架构识别的问题。
  2. 工程版本控制: 使用Git创建一个基础项目结构(如"Hello, RoboMaster!" 程序),并配置合理的.gitignore规则。
  3. 应用的容器化封装: 为你的项目编写一个 Dockerfile,并使用多阶段构建技术,实现轻量化的部署。
  4. 测试要求: 对于任务3,你的 test.sh 脚本应包含构建Docker镜像 (docker build) 和运行容器 (docker run) 的命令。

第三部分:机器人核心软件开发 (C++/Python 二选一)

背景: 机器人的"大脑"由无数高效、可靠的软件模块构成。本部分将深入探索构建这些模块所需的核心编程技术。

C++ 方向

  1. 并发传感器数据处理:
    • 场景: 机器人的决策依赖于多种传感器(如相机、IMU)的数据。这些传感器以不同频率并发地产生数据,需要一个高效的框架来处理。
    • 任务: 实现一个线程安全的队列类 ThreadPool
    • 测试要求: 请提供一个 test.cpp 文件,其中 main 函数要能创建多个生产者线程和消费者线程,并发地对 ThreadPool 实例进行操作,以验证其线程安全性。你的 test.shMakefile 必须能编译并运行这个 test.cpp
  2. 泛型编程与编译期优化:
    • 场景: 在机器人调试过程中,我们经常需要打印各种不同类型的数据结构(向量、自定义消息等)。编写一个通用的、高效的打印工具非常有用。
    • 任务: 编写一个通用的 print 函数,能够接受并打印任意数量、任意类型的参数,并能特化处理STL容器。
    • 测试要求: 提供一个 test.cpp 文件,在其中调用你的print函数,测试多种不同类型参数(如 int, double, std::string, std::vector<int>)的打印效果。
  3. 资源管理与矩阵运算:
    • 场景: 在机器人学中,从坐标变换到姿态表示,矩阵运算无处不在。一个高效且内存安全的矩阵类是基础。
    • 任务: 实现一个仅可移动 (Move-Only)Matrix 类,用于存储二维动态数组。
    • 具体实现要求:
      1. 内存布局: 内部数据必须以行主序 (Row-Major Order) 的方式存储在一维动态数组中(例如 new double[rows * cols])。
      2. 构造函数: 实现一个构造函数,接收行数 rows 和列数 cols,并动态分配所需的内存(例如,使用 new double[rows * cols])。
      3. 析构函数: 实现析构函数,正确释放构造函数中分配的内存,防止内存泄漏。
      4. 禁用拷贝: 使用 = delete 语法显式禁用拷贝构造函数和拷贝赋值运算符。
      5. 实现移动: 正确实现移动构造函数和移动赋值运算符。在移动操作后,原对象应处于一个有效的、可被安全析构的状态(例如,其内部指针为空)。
      6. 元素访问: 重载 operator(),使得可以通过 matrix(row, col) 的方式方便地访问和修改矩阵中的元素。其内部实现应类似于 return data[row * cols + col];
      7. (选做) 提供 get_rows()get_cols() 成员函数返回矩阵的维度。
    • 测试要求: 提供一个 test.cpp
      • 展示Matrix的正确创建和销毁。
      • 展示通过移动构造和移动赋值,将一个Matrix对象管理的资源“转移”给另一个对象。
      • 验证其拷贝构造和拷贝赋值已被禁用(尝试调用应导致编译错误,你可以将这部分代码注释掉,并在注释中说明)。
      • 展示元素访问功能。

Python 方向

  1. 异步设备通信框架:

    • 场景: 一个机器人通常需要通过网络与多个外部设备(如电机控制器、激光雷达、服务终端)进行通信。使用异步IO可以高效地处理这些并发的网络连接。
    • 任务: 使用 asyncio 编写一个客户端,它能并发地连接多个预设的TCP服务端口。
    • 测试要求: 你的 test.sh 脚本应首先在后台启动几个简单的netcat服务端(例如nc -l -p 8001 &),然后再运行你的Python客户端程序进行连接测试。
  2. 机器人行为插件化加载器:

    • 场景: 为了让机器人执行不同任务(如巡航、抓取、规避),我们希望将其"技能"设计成可插拔的插件,在需要时动态加载。
    • 任务: 利用元编程,实现一个SkillManager,它能自动发现并注册所有继承自BaseSkill的子类。
    • 测试要求: 提供一个 test.py 文件,在其中定义几个继承自BaseSkill的插件类,然后实例化SkillManager并调用插件,以展示其自动注册和调用功能。
  3. 高效处理海量机器人日志:

    • 场景: 机器人在运行时会产生巨大的日志文件(类似ROS bag),可能达到数GB,无法一次性加载到内存中分析。

    • 任务: 编写一个脚本,使用生成器 (Generator) 来逐行读取并分析一个大型日志文件。脚本需要能在常数级内存消耗下,统计出包含关键词“ERROR”的日志条目数量。

    • 测试: 我将提供一个1GB的log文件给你,你需要用这个文件对你的程序进行测试。

      下载地址


第四部分:基础算法与数据结构(C++/Python 二选一)

背景: 路径规划是机器人自主导航的核心技术之一。本部分要求你实现经典的A*搜索算法,为机器人在复杂的环境中找到最优路径。

任务:实现A*路径规划算法

  1. 场景描述: 在一个由二维栅格地图表示的环境中,一个机器人需要从起点(Start)移动到终点(Goal),只能直行,一次走一格。地图中包含无法通行的障碍物(Obstacles)。

  2. 实现要求:

    • 任务: 你的程序必须可以通过命令行接收参数,格式为:./your_program_name <map_file_path> <start_x> <start_y> <goal_x> <goal_y>

    • 正式测试文件 map.txt 内容: 请在你的项目中创建 map.txt 文件,并使用以下内容:(1为障碍物)如不能通行,需要输出“I can’t go to the postion (x,y).”(x,y为你输入的goal_x和goal_y)

      0 0 1 0 0
      0 1 0 1 0
      0 1 0 0 1
      1 1 0 1 1
      0 0 0 1 0
    • 输出: 程序需在标准输出打印出文本化的地图,并用 * 标记出从起点到终点的路径。

    • 测试要求: 你的 test.shMakefile 应该能编译程序,并使用 map.txt 和指定的起止点(例如,从 (0,0) 到 (4,4))来运行它。


第五部分:机器人系统集成与视觉算法

背景: 在现代机器人系统中,独立的软件模块需要通过通信框架(如ROS2)进行集成。本部分旨在考察你构建一个基本机器人感知应用的能力。

任务:创建并实现一个基础的视觉追踪ROS2包

总体目标: 创建一个名为 rm_vision_sim 且功能完整的ROS2功能包。该包将包含三个节点,它们协同工作,模拟一个机器人摄像头捕捉、检测并追踪一个移动目标的过程。

语言选择: C++ 或 Python 。


1. 节点功能详细说明

a) camera_node (图像发布者)

  • 功能: 模拟一个摄像头,持续生成图像数据流。
  • 实现细节:
    1. 无需真实摄像头。 请使用OpenCV创建一个 640x480 分辨率的黑色背景图像。
    2. 在该图像中,绘制一个半径为20像素的蓝色实心圆。
    3. 让这个蓝色圆在图像范围内随机缓慢移动
  • 发布接口:
    • 话题 (Topic): /image_raw
    • 消息类型 (Type): sensor_msgs/msg/Image
    • 发布频率: 10 Hz

b) detector_node (目标检测器)

  • 功能: 订阅原始图像流,检测其中的目标,并发布目标位置。
  • 实现细节:
    1. 使用OpenCV进行图像处理。
    2. 将接收到的BGR图像转换为HSV色彩空间
    3. 通过颜色阈值分割,找出图像中的蓝色区域。
    4. 计算蓝色区域轮廓的几何中心点 (Centroid)
  • 订阅接口:
    • 话题 (Topic): /image_raw
    • 消息类型 (Type): sensor_msgs/msg/Image
  • 发布接口:
    • 话题 (Topic): /target_position
    • 消息类型 (Type): geometry_msgs/msg/PointStamped (请填充 point.xpoint.y 字段,以及 header 中的时间戳)

c) logger_node (日志记录器)

  • 功能: 订阅目标位置信息,并将其打印到控制台,用于调试和验证。
  • 实现细节:
    1. 每接收到一条消息,就在终端(标准输出)打印出目标的x和y坐标。
    2. 打印格式示例:Target detected at: [x=320.5, y=240.1]
  • 订阅接口:
    • 话题 (Topic): /target_position
    • 消息类型 (Type): geometry_msgs/msg/PointStamped

2. 系统启动与测试要求

  1. Launch文件:

    • 请在你的 rm_vision_sim 功能包中创建一个名为 tracking_sim.launch.py 的launch文件。
    • 这个launch文件必须能够一次性启动上述全部三个节点。
  2. 统一测试 (test.sh):

    • 你的 test.sh 脚本或 Makefile 中的 test 目标必须能够自动化地完成以下流程:
      1. 使用 colcon build 编译整个ROS2工作区。
      2. source 正确的 setup.bash 文件。
      3. 使用 ros2 launch 命令启动你的 tracking_sim.launch.py 文件。
    • 脚本运行时,我们应该能看到 logger_node 在终端持续打印坐标信息。
  3. 验证说明 (README.md):

    • README.md 中,除了test.sh的说明,还需提供一个手动验证的方法。
    • 这个方法应告知学长学姐,在系统运行后,可以通过在新终端执行 ros2 topic echo /target_position 命令来查看 detector_node 发布的数据流,以此验证其功能是否正常。

算法鲁棒性分析 (理论题)

  • 问题: 在上述detector_node中,如果模拟的视频流引入了剧烈的光照变化(时亮时暗),简单的颜色阈值分割会很不稳定。请阐述至少两种可以提升检测鲁棒性的图像预处理或算法改进方法,并简述其原理。

第六部分:机器人感知算法基础

背景: 深度学习是现代机器人视觉感知系统的核心技术。本部分要求你为机器人训练一个目标识别模型。

数据集说明:CIFAR-10

任务:实现并训练一个CNN模型,用于CIFAR-10图像分类

技术栈二选一 (Python/PyTorch 或 C++/LibTorch):

  • Python (PyTorch): 使用torchvision自动下载并加载数据,完成模型训练。
  • C++ (LibTorch): 手动下载数据集的二进制版本,并自行编写C++ Dataset类来解析和加载数据,完成模型训练。

测试要求: 你的 README.md 必须提供开始训练的确切命令。你的 test.sh 脚本可以就是这个训练命令,或者是一个调用训练脚本的命令。

提示

学长建议还是用Pytorch好一些哦!不要把跨语言看得那么难。

如果你还是想用libtorch,请看下面的建议

C++ (LibTorch)

  1. 数据加载:
    • 你需要从官方网站手动下载数据集的 "CIFAR-10 binary version"
    • 二进制格式说明: 该数据集由多个文件组成,每个文件包含一系列3073字节的记录。每个记录的第1个字节是标签(0-9)后续的3072个字节依次是1024个红色像素、1024个绿色像素和1024个蓝色像素(32x32图像)。
    • 核心任务: 你的首要任务是编写一个能正确解析这些二进制文件的C++ Dataset类(继承自 torch::data::Dataset)。
    • 实现建议:
      • 先编写一个独立的函数,尝试从文件中正确读取并解析一条记录,将其转换为一个 torch::Tensor (图像) 和一个 torch::Tensor (标签)。
      • 验证图像Tensor的维度应为 (3, 32, 32)
      • 成功后,再将此逻辑封装到你的自定义Dataset类中。
  2. 实现要求:
    • 使用C++和LibTorch完成图像分类任务。你需要自行配置CMake以链接LibTorch,并用C++实现完整的训练与评估逻辑。
    • 将模型权重保存为.pt文件。

提交说明:

请在力所能及地完成任务,完成后,将你的Git仓库访问权限分享给学长学姐。我们期待看到你严谨的代码、清晰的文档以及解决问题时展现出的工程思维。

祝你一切顺利,期待在队伍里见到你!

逐雁创新机器人实验室