跳转至

第1章 开发环境搭建

本章目标

从零开始搭建 RoboMaster 视觉组的完整开发环境。完成本章后,你将拥有一个可以编译、调试、运行视觉自瞄程序的 Linux 工作环境,并理解每个工具在自瞄系统中的角色。

预计用时: 1-2 天(建议集中完成,不要分太多天)

前置知识: 无,本章面向零基础


1.1 Ubuntu 安装

这是什么

Ubuntu 是一个基于 Linux 的操作系统。RoboMaster 视觉开发几乎全部在 Linux 下完成,Windows 和 macOS 无法直接运行 ROS2 和大部分视觉算法框架。

为什么需要

  • ROS2(视觉组的核心框架)原生支持 Linux,在其他系统上运行需要大量额外配置
  • OpenCV、CUDA 等视觉/推理库在 Linux 下编译最稳定
  • 自瞄程序最终部署在嵌入式 Linux(如 Jetson / Radxa)上,开发环境和部署环境一致能避免大量兼容问题
  • Linux 下编译速度和调试体验远优于其他系统

三种安装方案对比

特性 双系统 WSL2 虚拟机
性能 原生,最好 接近原生 损耗约 10-20%
显卡支持 直接使用 有限(GPU 直通实验性) 需要显卡直通
安装难度 较高(涉及分区) 最低(Windows 内置) 中等(需下载虚拟机软件)
和 Windows 共存 需重启切换 同时使用 同时使用
USB 设备支持 直接支持 需要额外配置 需要 USB 转发
推荐场景 主力开发 日常学习/轻量开发 不想动 Windows 分区
推荐指数 ★★★★★ ★★★★☆ ★★★☆☆

新手建议

如果你是 Windows 用户,且是第一次使用 Linux,强烈建议先用 WSL2 或虚拟机入门。等你熟悉了基本操作之后,再考虑装双系统作为主力环境。如果你是 macOS 用户,虚拟机或远程服务器是更现实的方案。

双系统是指在同一台电脑上同时安装 Windows 和 Ubuntu,开机时可以选择进入哪个系统。

准备工作:

  • 一个 8GB 以上的 U 盘(制作启动盘会格式化 U 盘,请提前备份)
  • 至少 100GB 的空闲磁盘空间(建议 200GB+)
  • 下载 Ubuntu 22.04 LTS 镜像:官方下载页

重要提醒

分区操作有风险,操作不当可能丢失 Windows 数据。请务必提前备份重要文件!

步骤 1:制作启动盘

推荐使用 Rufus(Windows 下)制作启动 U 盘:

  1. 插入 U 盘,打开 Rufus
  2. 选择下载好的 .iso 镜像文件
  3. 分区类型选 GPT,目标系统选 UEFI
  4. 点击"开始",等待完成

步骤 2:为 Ubuntu 腾出磁盘空间

在 Windows 下操作:

  1. 右键"此电脑" → "管理" → "磁盘管理"
  2. 选择一个较大的分区(建议 D 盘),右键 → "压缩卷"
  3. 输入压缩大小(建议至少 100000 MB,即约 100GB)
  4. 压缩后会出现一块"未分配"空间,不需要做任何操作

步骤 3:从 U 盘启动安装

  1. 插入 U 盘,重启电脑
  2. 开机时按 F2/F12/Del(不同品牌不同)进入 BIOS 启动菜单
  3. 选择 U 盘启动
  4. 选择 "Install Ubuntu"
  5. 在安装类型时选择 "Install Ubuntu alongside Windows Boot Manager"(与 Windows 共存)
  6. 设置用户名、密码,等待安装完成

步骤 4:验证安装

安装完成后重启,你会看到一个启动菜单(GRUB),可以选择进入 Ubuntu 或 Windows。

# 进入 Ubuntu 后,打开终端(Ctrl+Alt+T),验证系统版本
lsb_release -a
# 输出应该包含: Ubuntu 22.04.x LTS

WSL2(Windows Subsystem for Linux 2)是微软官方提供的在 Windows 中运行 Linux 的方案,安装最简单,适合入门。

步骤 1:启用 WSL2

以管理员身份打开 PowerShell,执行:

# 启用 WSL(Windows 10 2004+ / Windows 11 原生支持)
wsl --install

# 如果上面的命令不可用,手动启用:
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

# 设置 WSL2 为默认版本
wsl --set-default-version 2

执行完毕后 重启电脑

步骤 2:安装 Ubuntu 22.04

# 从 Microsoft Store 安装,或用命令行
wsl --install -d Ubuntu-22.04

安装完成后会自动弹出 Ubuntu 终端,设置你的用户名和密码。

步骤 3:验证

# 在 Ubuntu 终端中
lsb_release -a
uname -a  # 查看内核版本,应该包含 microsoft 字样

步骤 4:安装图形界面(可选,视觉开发推荐)

WSL2 默认只有命令行。要使用图形界面(比如运行有 GUI 的调试工具),执行:

# 安装基础图形工具
sudo apt update && sudo apt install -y x11-apps

# 测试(应该弹出一个图形窗口)
xeyes

WSL2 的图形支持

Windows 11 和 Windows 10 21H2+ 已内置 WSLg,原生支持 Linux GUI 应用。如果你的系统版本较旧,需要手动安装 VcXsrv 作为 X Server。

虚拟机方案是在 Windows/macOS 中通过虚拟化软件创建一个完整的 Linux 系统,推荐使用 VirtualBox(免费)或 VMware Workstation Player(个人免费)。

步骤 1:安装虚拟机软件

步骤 2:创建虚拟机

  1. 打开虚拟机软件,选择"新建虚拟机"
  2. 选择下载好的 Ubuntu 22.04 .iso 镜像
  3. 分配资源:
    • 内存:建议 至少 4GB(8GB 更佳)
    • CPU 核心:建议 至少 2 核
    • 磁盘:建议 至少 80GB
    • 显存:建议 128MB
  4. 网络选择 桥接模式(方便后续 SSH 和远程连接)

步骤 3:安装 Ubuntu

虚拟机从 ISO 启动后,安装过程和双系统类似:

  1. 选择 "Install Ubuntu"
  2. 选择 "Erase disk and install Ubuntu"(这只会影响虚拟磁盘,不影响真实硬盘)
  3. 设置用户名密码,等待安装完成

步骤 4:安装增强功能

# VirtualBox:安装增强功能(支持共享剪贴板、拖拽文件、自动调整分辨率)
sudo apt update
sudo apt install -y build-essential dkms linux-headers-$(uname -r)

# 然后在虚拟机菜单栏:设备 → 安装增强功能
# 会挂载一个光盘,运行里面的 VBoxLinuxAdditions.run

macOS 无法原生运行 ROS2 和大部分 Linux 专用视觉工具。以下是两种可行方案:

方案 A:SSH 连接远程 Linux 服务器(推荐)

如果你有实验室的 Linux 服务器或旧电脑,直接 SSH 连接是最省事的方案。macOS 自带终端和 SSH 客户端,打开"终端"即可使用。后续的 SSH 章节会详细介绍连接方法。

方案 B:虚拟化 Ubuntu(本地运行)

UTM 安装步骤:

  1. UTM 官网 下载并安装 UTM
  2. 打开 UTM,点击"创建新虚拟机",选择"虚拟化"
  3. 选择下载好的 Ubuntu 22.04 ISO 镜像
  4. 分配资源:内存建议 至少 4GB,磁盘建议 至少 80GB
  5. 网络选择 桥接模式
  6. 按提示完成 Ubuntu 安装

安装后建议安装增强功能以支持共享剪贴板和自适应分辨率:

sudo apt update
sudo apt install -y spice-vdagent

Parallels Desktop 安装步骤更简单:

  1. 从 App Store 购买并安装 Parallels Desktop
  2. 打开后选择"文件 → 新建",导入 Ubuntu 22.04 ISO
  3. Parallels 会自动完成安装并配置好共享文件夹、剪贴板、显示器适配

Mac 用户建议

如果你日常使用 macOS,方案 A(SSH 远程服务器)是最推荐的,省去本地虚拟化的性能和配置麻烦。如果需要本地运行,UTM 是免费且够用的选择。Parallels 体验最流畅但需付费。无论哪种方案,所有编译和运行都在 Linux 侧完成,macOS 侧主要用来编辑代码和管理文件。

安装后必做的配置

无论你用哪种方式安装,进入 Ubuntu 后都要做以下基础配置:

# 1. 更新软件源和已安装的包
sudo apt update && sudo apt upgrade -y

# 2. 安装基础开发工具
sudo apt install -y build-essential git cmake vim curl wget

# 3. 设置 Git 使用中文显示(避免中文文件名显示为八进制)
git config --global core.quotepath false

1.2 基本终端命令

这是什么

终端(Terminal)是 Linux 下与计算机交互的文字界面。在 Linux 中,几乎所有操作都可以通过终端命令完成,而且很多操作只能通过终端完成。

为什么需要

  • ROS2、CMake、Git 等工具的主要操作方式都是命令行
  • 远程连接嵌入式设备(如 Jetson)时只能用终端
  • 命令行操作比图形界面更高效、更可复现
  • 团队的部署脚本、CI 流程都基于命令行

终端小知识

打开终端的快捷键:Linux 下按 Ctrl + Alt + T,macOS 下按 Cmd + Space 打开 Spotlight 搜索 Terminal。你看到的 username@hostname:~$ 叫做"命令提示符"(prompt),其中 ~ 代表你的家目录(/home/你的用户名)。

文件和目录操作

# pwd — 显示当前所在目录(Print Working Directory)
pwd
# 输出示例:/home/student

# ls — 列出当前目录下的文件(List)
ls                 # 列出文件名
ls -l              # 详细列表(显示权限、大小、日期)
ls -la             # 包含隐藏文件(以 . 开头的文件)
ls -lh             # 文件大小显示为 KB/MB 而非字节

# cd — 切换目录(Change Directory)
cd /home/student   # 切换到绝对路径
cd Documents       # 切换到当前目录下的 Documents 子目录
cd ..              # 返回上一级目录
cd ~               # 回到家目录(等同于直接输入 cd)
cd -               # 回到上一次所在的目录

# mkdir — 创建目录(Make Directory)
mkdir my_project           # 创建单个目录
mkdir -p src/vision/include # 递归创建多层目录(-p 表示自动创建父目录)

# cp — 复制文件(Copy)
cp file.txt backup.txt              # 复制文件
cp -r src/ src_backup/              # 复制目录(-r 表示递归复制)

# mv — 移动/重命名文件(Move)
mv old_name.txt new_name.txt        # 重命名
mv file.txt ~/Documents/            # 移动文件到另一个目录

# rm — 删除文件(Remove)⚠️ Linux 下没有回收站!
rm file.txt                         # 删除文件
rm -r build/                        # 删除目录及其所有内容
rm -rf build/                       # 强制删除,不提示确认(危险!慎用!)

# touch — 创建空文件或更新文件时间戳
touch new_file.txt

rm -rf 的教训

rm -rf / 会删除整个系统的所有文件,rm -rf ~ 会删除你所有的个人文件。在使用 rm 命令时 务必确认路径。很多程序员都经历过误删文件的惨痛教训。养成好习惯:删除前先 ls 确认目录内容。

查看文件内容

# cat — 显示文件全部内容(Concatenate)
cat CMakeLists.txt

# head / tail — 查看文件开头/末尾几行
head -20 log.txt          # 前 20 行
tail -20 log.txt          # 后 20 行
tail -f /var/log/syslog   # 实时追踪文件末尾(看日志常用,Ctrl+C 退出)

# less — 分页查看大文件
less large_file.txt       # 空格翻页,q 退出,/关键词 搜索

# wc — 统计行数、单词数
wc -l CMakeLists.txt      # 统计行数

搜索和查找

# grep — 在文件中搜索文本(Global Regular Expression Print)
grep "target" src/main.cpp              # 在文件中搜索 "target"
grep -r "Target" src/                   # 在整个目录中递归搜索
grep -rn "class" src/                   # 显示行号(-n)
grep -rni "armor" src/ --include="*.cpp" # 只在 .cpp 文件中搜索,忽略大小写

# find — 查找文件
find . -name "*.cpp"                    # 查找所有 .cpp 文件
find . -name "CMakeLists.txt"           # 查找所有 CMakeLists.txt
find /usr -name "libopencv*"            # 查找 OpenCV 库文件

# which — 查找命令的位置
which python3                            # 查看 python3 安装在哪里
which cmake

权限管理

# 查看文件权限
ls -l main.sh
# 输出:-rw-r--r-- 1 user group 1024 Jul 15 10:00 main.sh
#       ^^^^^^^^^^^
#       权限说明:r=读(4), w=写(2), x=执行(1)
#       三组分别代表:文件所有者 / 同组用户 / 其他用户

# chmod — 修改文件权限(Change Mode)
chmod +x run.sh               # 给脚本添加可执行权限
chmod 755 run.sh               # 所有者 rwx,其他人 rx
chmod 644 config.txt           # 所有者 rw,其他人只读

# chown — 修改文件所有者(需要 sudo)
sudo chown student:student my_file

软件包管理

# apt — Ubuntu 的软件包管理器(Advanced Package Tool)

# 更新软件源列表(获取最新的包信息)
sudo apt update

# 升级所有已安装的软件包
sudo apt upgrade -y

# 安装软件包
sudo apt install -y git cmake vim

# 卸载软件包
sudo apt remove package_name

# 搜索软件包
apt search opencv

# 查看已安装的包
dpkg -l | grep opencv

sudo 是什么

sudo 代表 "Super User DO",即以管理员权限执行命令。安装软件、修改系统配置等操作需要 sudo。第一次使用时会要求输入密码,密码不会显示任何字符(连 * 都没有),输入完毕直接回车即可。

macOS 上的包管理器是 Homebrew,功能类似于 Ubuntu 的 apt:

brew update                      # ≈ apt update
brew upgrade                     # ≈ apt upgrade
brew install vim                 # ≈ apt install vim
brew uninstall vim               # ≈ apt remove vim
brew list                        # ≈ dpkg -l(查看已安装的包)
brew search opencv               # ≈ apt search opencv

Homebrew 安装的软件默认在 /opt/homebrew/(Apple Silicon)或 /usr/local/(Intel),和 apt 的 /usr/ 路径不同,但使用逻辑非常相似。

进程管理

# 查看进程
ps aux                      # 查看所有进程
ps aux | grep my_program    # 查找特定进程

# 结束进程
kill PID                    # 发送终止信号(PID 是进程编号)
kill -9 PID                 # 强制终止(正常 kill 无效时使用)

# 后台运行程序
./my_program &              # & 让程序在后台运行
nohup ./my_program &        # 后台运行,关闭终端也不会停止

# 查看系统资源
top                         # 实时查看 CPU 和内存使用(q 退出)
htop                        # 更好看的 top(需要安装:sudo apt install htop)

常用快捷键

快捷键 功能
Tab 自动补全命令或文件名(按两次显示所有候选)
Ctrl + C 终止当前正在运行的程序
Ctrl + Z 挂起当前程序(用 fg 恢复)
Ctrl + R 搜索历史命令
Ctrl + A 光标跳到行首
Ctrl + E 光标跳到行尾
Ctrl + L 清屏(等同于 clear
上/下箭头 浏览历史命令
!! 重复上一条命令(常配合 sudo:sudo !!

1.3 Git 安装与使用

这是什么

Git 是一个分布式版本控制系统,用于追踪文件的变化历史。你可以把它理解为代码的"时光机"——可以回到任何一个历史版本,可以看到谁改了什么,可以多人同时修改同一个项目而互不冲突。

为什么需要

  • 视觉组代码由多人协作开发,Git 是协作的基础
  • 自瞄系统代码经常需要修改和调试,有了 Git 就不怕改坏——随时可以回退
  • 赛前和赛中的代码可能不同,Git 分支可以同时维护多个版本
  • 几乎所有开源项目(OpenCV、ROS2、rm_vision)都托管在 GitHub/Gitee 上

安装和配置

# 安装 Git(Ubuntu 通常已预装)
sudo apt install -y git

macOS 通过 Xcode Command Line Tools 已预装 Git。首次在终端输入 git 时,系统会提示安装。如需更新到最新版本:

brew install git
# 验证安装
git --version
# 输出示例:git version 2.34.1

# 配置用户信息(每次 commit 都会包含这些信息)
git config --global user.name "你的名字"
git config --global user.email "你的邮箱@example.com"

# 推荐配置
git config --global core.quotepath false     # 中文文件名正常显示
git config --global core.editor vim          # 设置默认编辑器
git config --global init.defaultBranch main  # 默认分支名用 main

核心概念

在学习命令之前,先理解 Git 的三个区域:

工作区 (Working Directory)   暂存区 (Stage)   本地仓库 (Repository)
        你编辑文件的地方      git add →        git commit →
                                                  最终存储
   ┌──────────────┐    git add     ┌──────────┐   git commit   ┌──────────────┐
   │   工作区      │  ──────────>   │  暂存区   │  ──────────>   │   本地仓库    │
   │ Working Dir  │               │  Stage    │               │ Repository   │
   └──────────────┘  <──────────   └──────────┘               └──────────────┘
                    git checkout                git reset

基本操作

# ============ 创建仓库 ============

# 方式1:在本地创建新仓库
mkdir my_project && cd my_project
git init

# 方式2:克隆远程仓库(最常用)
git clone https://github.com/your-team/rm_vision.git
cd rm_vision

# ============ 日常工作流 ============

# 查看当前状态(最常用的命令!)
git status

# 修改文件后,查看改了什么
git diff                    # 查看未暂存的修改
git diff --staged           # 查看已暂存的修改

# 添加文件到暂存区
git add src/main.cpp        # 添加单个文件
git add src/                # 添加整个目录
git add .                   # 添加所有修改(慎用!确认没有不需要的文件)

# 提交到本地仓库
git commit -m "feat: 添加装甲板识别模块"
#            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#            提交信息要有意义,描述你做了什么

# 查看提交历史
git log                     # 完整日志
git log --oneline           # 简洁版(一行一条)
git log --oneline --graph   # 带分支图形的简洁版
git log -5                  # 只看最近 5 条

# ============ 远程仓库操作 ============

# 查看远程仓库信息
git remote -v

# 推送到远程仓库
git push origin main        # 推送 main 分支到 origin 远程

# 从远程拉取更新
git pull origin main        # 拉取并合并远程 main 分支

分支操作

分支是 Git 最强大的功能之一。在视觉组中,你通常不会直接在 main 分支上开发,而是创建一个自己的分支。

# 查看分支
git branch                  # 查看本地分支
git branch -a               # 查看所有分支(包括远程)

# 创建并切换到新分支
git checkout -b feature/my-armor-detector
# 等同于:
# git branch feature/my-armor-detector
# git checkout feature/my-armor-detector

# 在新分支上开发、提交...
git add .
git commit -m "feat: 实现基础装甲板检测"

# 切换回主分支
git checkout main

# 合并分支到 main
git merge feature/my-armor-detector

# 删除已合并的分支
git branch -d feature/my-armor-detector

提交信息规范

好的提交信息能让团队快速理解每次修改的内容。推荐遵循以下格式:

<类型>: <简短描述>

<详细说明(可选)>

常用的类型:

类型 含义 示例
feat 新功能 feat: 添加能量机关识别
fix 修复 bug fix: 修复 PnP 解算崩溃问题
docs 文档 docs: 更新 README 安装说明
refactor 重构 refactor: 拆分装甲板分类器
chore 构建/工具 chore: 更新 CMake 配置

处理冲突

当两个人同时修改了同一个文件的同一部分,合并时会产生冲突:

# 冲突的文件会显示如下标记:
<<<<<<< HEAD
你的修改
=======
别人的修改
>>>>>>> other-branch

解决步骤:

  1. 打开冲突文件,找到 <<<<<<< 标记
  2. 手动决定保留哪些内容(可能需要两种修改都保留)
  3. 删除所有 <<<<<<<=======>>>>>>> 标记
  4. git add 解决后的文件
  5. git commit 完成合并

1.4 VSCode 安装与配置

这是什么

Visual Studio Code(VSCode)是微软开发的免费代码编辑器,是目前最流行的代码编辑器之一。它轻量、快速,通过插件可以支持几乎任何编程语言和工具。

为什么需要

  • C/C++ 开发需要语法高亮、自动补全、跳转定义等功能,记事本做不到
  • CMakeLists.txt 的语法高亮和智能提示能避免很多配置错误
  • Remote SSH 插件让你可以在本地编辑远程服务器/嵌入式设备上的代码
  • 集成终端和调试器让你无需切换多个窗口

安装

# 方式1:通过官方仓库安装(推荐)
sudo apt install -y wget gpg
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
sudo install -o root -g root -m 644 packages.microsoft.gpg /etc/apt/trusted.gpg.d/
sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/trusted.gpg.d/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list'
sudo apt update
sudo apt install -y code

# 方式2:通过 snap 安装(更简单)
sudo snap install code --classic

直接从 VSCode 官网 下载 Windows 安装包安装即可。

如果你使用的是 WSL2,VSCode 安装后会自动支持 WSL 远程连接。在 WSL 终端中输入:

code .

VSCode 会自动安装 WSL 远程扩展并在 WSL 环境中打开当前目录。

# 通过 Homebrew 安装(推荐)
brew install --cask visual-studio-code

或者从 VSCode 官网 下载 .dmg 安装包,拖入 Applications 文件夹即可。

必装插件

安装完 VSCode 后,需要安装以下插件。在 VSCode 左侧栏点击"扩展"图标(或按 Ctrl+Shift+X),搜索并安装:

C/C++ 开发核心:

插件名称 功能 重要程度
C/C++ 代码高亮、智能补全、调试 ★★★★★
CMake CMakeLists.txt 语法支持 ★★★★★
CMake Tools CMake 项目管理和构建 ★★★★★
C/C++ Extension Pack 包含上述多个 C++ 相关插件 ★★★★☆

远程开发:

插件名称 功能 重要程度
Remote - SSH SSH 远程连接开发 ★★★★★
Remote - SSH: Editing SSH 远程编辑配置文件 ★★★★☆
Remote - WSL WSL 远程连接 ★★★★★(WSL 用户必装)

效率提升:

插件名称 功能 重要程度
GitLens 增强 Git 功能,查看每行代码的修改历史 ★★★★☆
Chinese (Simplified) VSCode 中文界面 ★★★☆☆
Clang-Format 代码格式化 ★★★☆☆

批量安装命令(在 VSCode 终端中执行):

code --install-extension ms-vscode.cpptools
code --install-extension ms-vscode.cmake-tools
code --install-extension twxs.cmake
code --install-extension ms-vscode-remote.remote-ssh
code --install-extension eamodio.gitlens

VSCode 基本使用

# 在终端中用 VSCode 打开目录或文件
code .                      # 打开当前目录
code src/main.cpp           # 打开指定文件
code /path/to/project       # 打开指定目录

# 快捷键速查
# 功能                 Linux / Windows        macOS
# 快速打开文件         Ctrl+P                 Cmd+P
# 命令面板             Ctrl+Shift+P           Cmd+Shift+P
# 打开/关闭终端        Ctrl+`                 Cmd+`
# 打开/关闭侧边栏      Ctrl+B                 Cmd+B
# 跳转到定义           F12                    F12
# 全局搜索             Ctrl+Shift+F           Cmd+Shift+F
# Git 面板             Ctrl+Shift+G           Cmd+Shift+G
# 启动调试             F5                     F5

配置 C++ 开发环境

在项目根目录创建 .vscode/settings.json

{
    "C_Cpp.default.cppStandard": "c++17",
    "C_Cpp.default.cStandard": "c17",
    "cmake.buildDirectory": "${workspaceFolder}/build",
    "cmake.configureOnOpen": true,
    "editor.formatOnSave": true,
    "files.associations": {
        "*.hpp": "cpp",
        "*.h": "cpp"
    }
}

1.5 SSH 远程连接

这是什么

SSH(Secure Shell)是一种加密的远程连接协议,让你可以在本地电脑上操控远程服务器。在视觉组中,你需要通过 SSH 连接到嵌入式设备(如 Jetson Nano / Radxa Rock)上运行自瞄程序。

为什么需要

  • 自瞄程序最终运行在装在机器人上的嵌入式设备上,你不可能每次都把显示器接到设备上
  • 赛场上的调试和部署全部通过 SSH 完成
  • SSH 也是 VSCode Remote SSH 的底层技术,实现本地编辑远程代码

SSH 密钥对生成

SSH 登录有两种方式:密码登录和密钥登录。密钥登录更安全且可以免密,是推荐方式。

# 生成 SSH 密钥对
ssh-keygen -t ed25519 -C "your_email@example.com"

# 执行后会出现:
# Generating public/private ed25519 key pair.
# Enter file in which to save the key (/home/student/.ssh/id_ed25519):  ← 直接回车用默认路径
# Enter passphrase (empty for no passphrase):  ← 直接回车设为空密码(方便后续免密)
# Enter same passphrase again:  ← 再次回车

# 查看生成的密钥
ls ~/.ssh/
# id_ed25519      ← 私钥(绝对不能泄露!不能发给任何人!)
# id_ed25519.pub  ← 公钥(可以随意分发)

私钥安全

id_ed25519 是你的私钥,永远不要发送给任何人、上传到 GitHub、或放在共享目录里。如果私钥泄露,别人可以冒充你登录所有你配置过的服务器。只把公钥(.pub 文件)配置到目标服务器上。

免密登录配置

将公钥复制到远程服务器:

# 一行命令完成免密配置(推荐)
ssh-copy-id username@remote_host_ip

# 例如:
ssh-copy-id radxa@192.168.1.100

# 输入一次密码后,以后就不用再输入了
# 测试连接
ssh radxa@192.168.1.100

ssh-copy-id 失败怎么办

如果 ssh-copy-id 不可用(比如目标设备是 Windows 或嵌入式精简系统),可以手动复制:

# 在本地查看公钥内容
cat ~/.ssh/id_ed25519.pub

# 复制输出的内容,然后登录到远程服务器,执行:
mkdir -p ~/.ssh
echo "粘贴你的公钥内容" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

SSH Config 文件

当你管理多个远程设备时(比如多台机器人),每次输入完整 SSH 命令很麻烦。通过配置 ~/.ssh/config 文件,可以用简单别名快速连接。

# 编辑 SSH 配置文件
vim ~/.ssh/config

写入以下内容:

# 机器人的嵌入式设备
Host robot1
    HostName 192.168.1.100
    User radxa
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Host robot2
    HostName 192.168.1.101
    User radxa
    Port 22
    IdentityFile ~/.ssh/id_ed25519

# 实验室开发服务器
Host dev-server
    HostName 10.0.0.50
    User student
    Port 22
    IdentityFile ~/.ssh/id_ed25519

配置之后,连接就变得非常简单:

# 之前
ssh radxa@192.168.1.100 -p 22 -i ~/.ssh/id_ed25519

# 之后
ssh robot1

SSH 文件传输

# scp — 安全复制文件到远程/从远程复制
scp local_file.txt robot1:~/                    # 上传文件到远程家目录
scp -r ./build/ robot1:~/rm_vision/             # 上传整个目录
scp robot1:~/log.txt ./                         # 从远程下载文件

# rsync — 更强大的同步工具(增量传输,速度更快)
rsync -avz --progress ./build/ robot1:~/rm_vision/build/

SSH 常用调试技巧

# 查看详细连接信息(排查问题时使用)
ssh -v robot1
# -v 是 verbose 模式,会显示连接的每一步细节

# 保持连接活跃(防止长时间无操作后断开)
# 在 ~/.ssh/config 中添加:
# ServerAliveInterval 60
# ServerAliveCountMax 3

# 端口转发(将远程端口映射到本地,常用于查看远程的 Web 界面)
ssh -L 8080:localhost:80 robot1
# 然后在本地浏览器访问 http://localhost:8080 即可访问远程的 Web 服务

1.6 CMake 基础

这是什么

CMake 是一个跨平台的构建系统生成器。你编写 CMakeLists.txt 来描述项目如何编译,CMake 会自动生成 Makefile(或其他构建系统),然后你用 make 来实际编译。

为什么需要

  • C++ 项目没有像 Python 那样的统一包管理器,编译配置是一个独立的步骤
  • 自瞄系统包含多个源文件、多个库(OpenCV、ROS2 等),手动编译命令会非常长
  • CMake 是行业标准,ROS2、OpenCV、rm_vision 都用 CMake 构建
  • 掌握 CMake 是读懂和修改视觉组代码的前提

一个最简单的例子

先理解整个构建流程:

源代码 (.cpp) + CMakeLists.txt
      cmake       生成 Makefile
       make       编译生成可执行文件
    ./my_program  运行

创建一个最小项目:

mkdir hello_cmake && cd hello_cmake

main.cpp

#include <iostream>

int main() {
    std::cout << "Hello, RoboMaster!" << std::endl;
    return 0;
}

CMakeLists.txt

# 指定 CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)

# 定义项目名称和使用的语言
project(hello_cmake LANGUAGES CXX)

# 添加可执行文件目标
# 语法:add_executable(目标名 源文件...)
add_executable(my_program main.cpp)

构建和运行:

# 1. 创建并进入构建目录(out-of-source build,保持源码目录干净)
mkdir build && cd build

# 2. 运行 CMake,生成 Makefile
cmake ..
# 输出示例:
# -- The CXX compiler identification is GNU 11.4.0
# -- Configuring done
# -- Generating done
# -- Build files have been written to: /home/student/hello_cmake/build

# 3. 编译
make
# 或者用 cmake --build . (更通用的写法)

# 4. 运行
./my_program
# 输出:Hello, RoboMaster!

为什么要在 build 目录中构建?

在源码目录外构建(out-of-source build)是一个好习惯。这样编译生成的中间文件不会污染源码目录,清理时只需删除 build 目录即可。rm_vision 和几乎所有 CMake 项目都采用这种方式。

CMakeLists.txt 详细语法

添加多个源文件

cmake_minimum_required(VERSION 3.10)
project(armor_detector LANGUAGES CXX)

# 方式1:逐个列出源文件
add_executable(detector
    src/main.cpp
    src/armor_detector.cpp
    src/classifier.cpp
)

# 方式2:用 GLOB 自动收集(不推荐用于大项目,新增文件不会自动发现)
file(GLOB SOURCES "src/*.cpp")
add_executable(detector ${SOURCES})

# 方式3:推荐做法——显式列出
set(SOURCES
    src/main.cpp
    src/armor_detector.cpp
    src/classifier.cpp
)
add_executable(detector ${SOURCES})

头文件搜索路径

# 告诉编译器去哪里找头文件(#include "xxx.h")
target_include_directories(detector PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)
# 现在可以在 src/main.cpp 中使用:#include "armor_detector.hpp"

链接第三方库(OpenCV 为例)

# 查找 OpenCV 库
find_package(OpenCV REQUIRED)

# 链接到目标
target_link_libraries(detector ${OpenCV_LIBS})
# 现在可以在代码中使用 #include <opencv2/opencv.hpp>

完整的项目结构

一个中等规模的视觉项目通常有这样的结构:

my_project/
├── CMakeLists.txt          # 顶层 CMake 配置
├── include/                # 头文件目录
│   └── armor_detector.hpp
├── src/                    # 源文件目录
│   ├── main.cpp
│   └── armor_detector.cpp
├── config/                 # 配置文件
│   └── params.yaml
└── build/                  # 构建目录(不加入 Git)

对应的 CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(armor_detector LANGUAGES CXX)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 查找依赖库
find_package(OpenCV REQUIRED)

# 创建可执行文件
add_executable(detector
    src/main.cpp
    src/armor_detector.cpp
)

# 设置头文件搜索路径
target_include_directories(detector PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)

# 链接库
target_link_libraries(detector ${OpenCV_LIBS})

常用 CMake 命令速查

cmake ..                        # 基本配置(使用默认编译器)
cmake -DCMAKE_BUILD_TYPE=Release ..    # 指定 Release 模式(优化,无调试信息)
cmake -DCMAKE_BUILD_TYPE=Debug ..      # Debug 模式(有调试信息,适合调试)
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..  # 生成 compile_commands.json(VSCode 需要)

cmake --build .                 # 编译(等同于 make,跨平台通用)
cmake --build . -j8             # 用 8 个线程并行编译(更快)
cmake --build . --target clean  # 清理编译产物

make -j$(nproc)                 # 用所有 CPU 核心编译(Linux 最常用的写法)
# macOS 替代:make -j$(sysctl -n hw.logicalcpu)
make clean                      # 清理编译产物

1.7 Docker 简介

这是什么

Docker 是一个容器化平台,可以把应用程序及其所有依赖打包成一个"容器"(Container)。你可以把容器理解为一个极轻量级的虚拟机——它有自己的文件系统、网络环境和运行空间,但共享宿主机的操作系统内核,启动只需几秒。

传统方式:                        Docker 方式:
┌──────────────┐                 ┌──────────────────────────┐
│  虚拟机 A     │  ← 很重        │  容器 1  │  容器 2  │  ... │ ← 很轻
│  完整 OS     │                 │  ROS2   │  OpenCV  │      │
│  应用程序     │                 │  应用    │  应用    │      │
├──────────────┤                 ├──────────────────────────┤
│  虚拟机 B     │                 │      Docker 引擎         │
│  完整 OS     │                 ├──────────────────────────┤
│  应用程序     │                 │      宿主机 OS            │
├──────────────┤                 └──────────────────────────┘
│  宿主机 OS    │
└──────────────┘

为什么视觉组需要 Docker

环境地狱

想象一下这个场景:新队员加入,需要配环境。ROS2 Humble 需要 Ubuntu 22.04,OpenCV 需要特定版本,还有各种编译依赖。按照教程装了一天,最后编译还是报错,因为某个库版本不兼容。这种情况在 C++ 开发中非常常见,俗称"环境地狱"(Dependency Hell)。

Docker 解决了以下问题:

问题 没有 Docker 有 Docker
新队员配环境 跟着文档装 1-2 天,可能失败 docker pull 一条命令,几分钟搞定
不同队员环境不一致 "在我电脑上能跑啊" 所有人用同一个镜像,100% 一致
ROS2 版本切换 卸载重装,可能搞坏系统 换一个镜像,互不影响
比赛现场部署 紧急配环境,手忙脚乱 赛前打包好镜像,现场直接运行

安装 Docker

# 卸载旧版本(如果有)
sudo apt remove -y docker docker-engine docker.io containerd runc

# 安装依赖
sudo apt update
sudo apt install -y ca-certificates curl gnupg

# 添加 Docker 官方 GPG 密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 添加 Docker 仓库
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 将当前用户添加到 docker 组(免 sudo)
sudo usermod -aG docker $USER

# 需要重新登录终端(或重启)才能生效
# 临时方案:在当前终端执行
newgrp docker

# 验证安装
docker run hello-world
# 看到 "Hello from Docker!" 就说明安装成功了
# 通过 Homebrew 安装 Docker Desktop(推荐)
brew install --cask docker

安装完成后打开 Docker Desktop 应用,等待引擎启动(菜单栏出现 Docker 图标),然后验证:

docker run hello-world

Docker 基本命令

# ============ 镜像操作 ============

# 查看本地镜像
docker images

# 从 Docker Hub 拉取镜像
docker pull ubuntu:22.04

# 删除镜像
docker rmi ubuntu:22.04

# ============ 容器操作 ============

# 运行一个容器(交互模式)
docker run -it ubuntu:22.04 /bin/bash
# -i: 交互模式
# -t: 分配伪终端
# 执行后进入容器的 bash,exit 退出并停止容器

# 运行一个容器(后台模式)
docker run -d --name my_container ubuntu:22.04 sleep infinity
# -d: 后台运行
# --name: 给容器起名字

# 查看正在运行的容器
docker ps

# 查看所有容器(包括已停止的)
docker ps -a

# 进入正在运行的容器
docker exec -it my_container /bin/bash

# 停止/启动/删除容器
docker stop my_container
docker start my_container
docker rm my_container

# ============ 镜像构建 ============

# 根据 Dockerfile 构建镜像
docker build -t my_vision_env .

# 保存/加载镜像(用于离线传输到嵌入式设备)
docker save my_vision_env > vision_env.tar
docker load < vision_env.tar

Dockerfile 示例

在项目根目录创建 Dockerfile

# 基础镜像
FROM ubuntu:22.04

# 设置非交互模式(避免安装过程中的交互提示)
ENV DEBIAN_FRONTEND=noninteractive

# 安装基础依赖
RUN apt-get update && apt-get install -y \
    build-essential \
    cmake \
    git \
    libopencv-dev \
    && rm -rf /var/lib/apt/lists/*

# 设置工作目录
WORKDIR /workspace

# 复制项目文件
COPY . .

# 编译项目
RUN mkdir build && cd build && cmake .. && make -j$(nproc)

# 默认启动命令
CMD ["./build/my_program"]

视觉组通常不用自己写 Dockerfile

rm_vision 项目通常会提供预构建好的 Docker 镜像或 Dockerfile,你只需要 docker pulldocker build 即可。了解 Docker 基本概念和命令是为了能看懂项目的使用说明并进行简单的定制。


1.8 在自瞄系统中的应用

前面介绍了七个工具/概念。下面用一张表总结它们在自瞄系统开发中的具体应用场景:

工具 在自瞄系统中的具体用法
Ubuntu 运行 ROS2 节点、编译 OpenCV、训练/推理模型;嵌入式设备上也运行 Ubuntu
终端命令 cat 查看日志,grep 搜索错误,chmod 赋予脚本权限,top 监控 CPU 占用
Git 管理自瞄代码版本,团队协作开发不同模块(检测、跟踪、通信)
VSCode 编写和调试 C++ 代码,Remote SSH 编辑嵌入式设备上的代码
SSH 连接 Jetson/Radxa 部署程序、查看运行日志、赛场调试
CMake 编译整个自瞄系统,管理 OpenCV、ROS2、串口库等依赖
Docker 快速搭建一致的开发/部署环境,避免环境问题

典型开发流程示例

下面是一个完整的视觉组日常工作流程,展示每个工具如何串联使用:

# === 1. 早上到实验室,开始工作 ===

# 打开终端,拉取团队最新代码
cd ~/rm_vision
git pull origin main

# 查看今天有哪些更新
git log --oneline -5

# === 2. 创建自己的开发分支 ===

git checkout -b feature/new-armor-classifier

# === 3. 用 VSCode 打开项目,开始写代码 ===

code .

# 在 VSCode 中编写新的分类器代码...
# VSCode 的 C++ 插件提供自动补全和跳转定义功能
# CMake Tools 插件可以一键编译(Ctrl+Shift+P → CMake: Build)

# === 4. 本地编译测试 ===

cd build
cmake .. && make -j$(nproc)

# 运行测试
./rm_vision_node --test

# 用 grep 在日志中查找关键信息
cat output.log | grep "armor"
cat output.log | grep -i "error"    # 忽略大小写搜索

# === 5. 提交代码 ===

cd ~/rm_vision
git add src/new_classifier.cpp include/new_classifier.hpp
git commit -m "feat: 实现新的装甲板颜色分类器"

# === 6. 推送到远程仓库 ===

git push origin feature/new-armor-classifier

# === 7. 部署到机器人上测试 ===

# 用 SSH 连接到机器人的嵌入式设备
ssh robot1

# 在嵌入式设备上拉取代码并编译
cd ~/rm_vision
git pull
cd build && cmake .. && make -j4

# 运行自瞄程序
./rm_vision_node

# 查看运行日志
tail -f output.log

# === 8. 如果使用 Docker ===

# 在嵌入式设备上用 Docker 运行(环境一致性有保障)
docker pull your-team/rm_vision:latest
docker run --rm --privileged \
    -v /dev/video0:/dev/video0 \
    your-team/rm_vision:latest

在 VSCode 中远程调试嵌入式设备

VSCode 的 Remote SSH 让你可以像编辑本地文件一样编辑远程设备上的代码:

  1. Cmd+Shift+P(macOS)/ Ctrl+Shift+P(Linux),输入 Remote-SSH: Connect to Host
  2. 选择你配置好的 robot1(来自 ~/.ssh/config
  3. VSCode 会自动连接到远程设备并安装服务端
  4. 打开远程设备上的 ~/rm_vision 目录
  5. 现在你可以在本地 VSCode 中编辑远程文件,使用远程终端编译和运行

本章小结

恭喜你完成了开发环境搭建!

现在你已经拥有了:

  • 一个可以运行的 Linux 环境
  • 基本的终端操作能力
  • Git 版本控制工具
  • VSCode 代码编辑器及必要插件
  • SSH 远程连接能力
  • CMake 构建系统的基础知识
  • Docker 容器化的基本概念

这些是视觉组开发的基础设施。接下来的章节将正式进入 C++ 编程学习。

练习

动手实践是最好的学习方式。请完成以下练习:

  • 安装 Ubuntu 22.04(任意方式),成功进入桌面/终端
  • 在终端中用 mkdircdls 创建并浏览一个目录结构
  • 在 GitHub 上注册账号,创建一个仓库,用 Git 完成 clone → 修改 → add → commit → push 全流程
  • 安装 VSCode 及 C/C++ 相关插件,成功打开一个 C++ 文件并看到语法高亮
  • 生成 SSH 密钥对,配置免密登录到另一台机器(可以和队友互相配置)
  • 编写一个 CMakeLists.txt,编译一个包含两个 .cpp 文件的项目
  • 安装 Docker,运行 docker run hello-world

延伸阅读