
做一个机器人项目尤其是双足人形这种体量的整机环境配置会占掉前期开发至少三分之一的时间。Thor 是我们这边一个双足人形项目的内部代号计算平台选定的是 Jetson 系列所以完整地把 Jetson 刷机、系统初始化、AI 推理框架、ROS 中间件、远程调试、性能调优这一整条链路都走了一遍。这篇文章是这次配置过程的复盘也是给后面接手 Thor 或者类似边缘计算平台的朋友留一份能直接照着做的资料。我会把每个环节里为什么这么做也讲清楚免得你看着教程敲完命令一旦出错就不知道怎么排查。Jetson 最坑的不是命令本身而是版本之间互相咬合的关系以及刷机时各种莫名其妙的网络和分区问题。这些我都会单独拎出来说。1. Thor项目为什么把“大脑”交给Jetson AGX Orin1.1 三块主流 Jetson 板卡的实际对比Thor 在方案选型的时候我们认真对比过 Jetson Nano、Jetson Xavier NX 和 Jetson AGX Orin 三块板子。很多人一上来就盯着算力数字看实际做完整机你会发现人形机器人对平台的要求不只算力一条。平台AI 算力内存带宽典型功耗人形场景表现适合角色Jetson Nano0.5 TOPS低5-10W只能跑单路轻量模型原型验证Jetson Xavier NX21 TOPS中等10-25W能跑单目感知 简单控制早期样机Jetson AGX Orin 64GB275 TOPS高15-60W多路视觉 大模型 实时控制主力平台Thor 的传感器配置是双目相机、一台深度相机、IMU、六维力传感器加上麦克风阵列同时还要跑目标检测、语义分割、行人跟踪、路径规划和语音语义理解。这里面任何一路单独拿出来Jetson Nano 都能勉强凑合但放在同一时刻、同一个系统里跑内存带宽和 GPU 算力立刻就是瓶颈。AGX Orin 64GB 版本我们实测下来在 MAXN 模式下可以同时吃下多路视频流和若干个小模型内存余量也够跑一些 7B 量级的量化大模型。1.2 人形机器人对算力平台的硬性要求人形机器人和普通机器人最大的区别在于自由度多、传感器多、实时性要求高。Thor 的全身控制周期要维持在几百赫兹到上千赫兹这意味着运动控制任务对 CPU 实时性非常敏感不能把整个系统全压在 GPU 调度上。Jetson AGX Orin 的 CPU 是 12 核 ARM Cortex-A78AE这个配置在处理实时控制、通信调度和传感器数据解析时要比 Xavier NX 宽裕很多。GPU 则负责视觉感知和模型推理两边互不干扰。AGX Orin 还带 DLA深度学习加速器适合跑一些固定输入尺寸的小模型比如光流、姿态估计之类功耗比 GPU 低不少也省电。内存带宽是特别容易被忽略的指标。多路摄像头数据进内存后要同时被 CPU、GPU 和 DLA 访问带宽不够会直接表现为画面卡顿、推理延迟抖动。AGX Orin 64GB 的内存带宽比 Xavier NX 高了一个量级实测跑 BeVFormer 这类需要大量张量运算的模型时差距非常明显。注意Thor 这样的整机项目真正决定上限的不是 GPU 有多强而是整个平台的 IO 吞吐和内存带宽。选型时不要只看 TOPs 数字。1.3 供电、散热与机械固定的基线AGX Orin 满载功耗接近 60W这块热量不是散热片能随便压住的。Thor 项目里我们直接把板卡固定在专用的铝合金托架上散热风扇采用主动风冷确保长期运行温度控制在安全范围。供电方面AGX Orin 对电压波动比较敏感机器人电池供电时要注意 DC-DC 模块的纹波。我们最初用一块普通稳压模块供电满载推理时偶尔出现系统重启后来换成了带缓启动的电源模块才稳定下来。我的建议是在装机之前先把环境配置全部完成因为刷机、编译、跑 AI 模型时板子负荷很大散热和供电不稳的话会不断出现各种奇怪的故障让你分不清是硬件问题还是软件问题。2. 刷机与系统初始化的那些容易翻车的地方2.1 SDK Manager 刷机的流程与网络问题Thor 使用的 Jetson AGX Orin 出厂不带系统需要自己刷入 JetPack。NVIDIA 官方推荐用 SDK Manager 完成整套流程宿主机上安装 SDK Manager连接 usb 线让设备进入恢复模式然后选择要安装的 JetPack 版本和组件点击开始刷写。# 宿主机上安装 sdkmanager sudo apt install sdkmanager sdkmanager --cli刷机有几个容易翻车的地方。第一个是网络SDK Manager 需要从 NVIDIA 服务器下载好几个 GB 的系统镜像网络不稳定会一直卡在下载阶段看起来像卡死实际是网络断了。第二个是宿主机磁盘空间JetPack 5.x 刷机后宿主机里会留一份镜像副本空间不足会在刷机过程中报错。第三个是 USB 连接不稳定建议用短而粗的 USB-C 线不要用延长线。2.2 换源、基础依赖与版本绑定JetPack 刷完之后系统是干净但原始的 Ubuntu 20.04 定制版自带 CUDA、cuDNN、TensorRT 等全套 NVIDIA 组件。这时候很多人会急着装东西但我建议先把软件源、pip 源换掉再装一组通用工具链。# 使用 apt 源替换后更新 sudo apt update sudo apt upgrade -y sudo apt install -y git curl wget cmake build-essential python3-pip \ libopenblas-dev libopenmpi-dev一个很重要的点JetPack 自带了 CUDA 工具链不要自己再装一份nvidia-cuda-toolkit也不要单独apt install cuda。这样会和 NVIDIA 自带的 CUDA 环境打架导致torch.cuda.is_available()时好时坏非常恶心。另外不要随意升级内核。JetPack 的 kernel 和 NVIDIA 驱动是配对发布的升级内核后经常会碰到驱动加载失败、Wi-Fi 模块失效这种问题。我的原则是JetPack 默认内核能用就坚决不动。2.3 NVMe 扩容与 SWAP 设置Thor 的工程目录里有模型权重、数据集、日志和 Docker 镜像动辄几十 GB。AGX Orin 自带的 eMMC 存储根本不够用所以必须外接 NVMe SSD。装好之后把它格式化并挂载到/home或者专门的数据目录。# 查看 NVMe 设备 sudo lsblk # 格式化并挂载到 /mnt/ssd sudo mkfs.ext4 /dev/nvme0n1 sudo mkdir -p /mnt/ssd sudo mount /dev/nvme0n1 /mnt/ssd编译大型工程如 PyTorch、BeVFormer 或者 mmcv 时内存不够会直接 OOM。Jetson 系列本身没有那么大内存我建议给系统加 SWAP。用文件形式的 swapfile 而不是分区灵活性更好sudo fallocate -l 16G /var/swapfile sudo chmod 600 /var/swapfile sudo mkswap /var/swapfile sudo swapon /var/swapfile加完之后用free -h确认。这块投入非常值得我们编译 mmcv 的时候16G SWAP 基本保证了过程不会中途被杀。2.4 开机 Wi-Fi 消失的排查经验Jetson 开机没有 WiFi 是个高频问题Thor 开发早期我也遇到过。常见原因有三个驱动没有加载、NetworkManager 状态异常、国家码区域配置不对。# 查看无线网卡是否被发现 lspci -nn | grep -i network # 查看驱动加载状态 dmesg | grep -i wireless # 尝试重新开启 WiFi nmcli radio wifi on如果lspci里看不到无线网卡多半是驱动模块没加载如果能看到但nmcli扫描不到 AP检查国家码以及天线接口是否接好。不要轻易去重新编译内核驱动大部分时候问题出在刷机后系统保留的旧状态。注意如果同时插着网线系统有时会优先走有线网络Wi-Fi 连上但上不了外网检查一下路由优先级不要白折腾半天。3. AI训练/推理链路的版本对齐比别人少踩一半坑3.1 为什么不能直接 pip install torchJetson 是 ARM64 架构且 JetPack 里的 CUDA 是 NVIDIA 定制版本PyPI 官方源里的 torch 预编译包是给 x86_64 的 CUDA 12 环境用的直接装会显示安装成功但import torch时要么报错要么没有 CUDA 支持。NVIDIA 官方提供了 Jetson 专用的 torch wheel比如 JetPack 5.1.3 对应 CUDA 11.8对应 Python 3.8torch 版本是 2.1.0 系列的定制包。你需要在 NVIDIA 官方论坛的 PyTorch for Jetson 页面里找到对应版本的下载链接然后pip3 install --no-cache-dir torch-2.1.0a0...cp38-cp38-linux_aarch64.whl一定要核对三个要素JetPack 版本、CUDA 版本、Python 版本缺一个都会在运行时出问题。3.2 Miniforge PyTorch 的依赖隔离Jetson 上做 AI 项目我推荐用 Miniforge 而不是 Anaconda。因为 Anaconda 对 ARM 架构支持不好Miniforge 自带 conda-forge 源能正常在 aarch64 上安装 Python 和包。# 安装 Miniforge wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh bash Miniforge3-Linux-aarch64.sh # 创建独立环境 conda create -n thor python3.8 conda activate thor创建环境后优先用 pip 安装 PyTorch不要用 conda 去装 cudatoolkit。Jetson 系统里已经有完整的 CUDA 库了conda 里再装一份容易变成两个 CUDA 环境互相干扰。系统 CUDA 保持不变只让 conda 管理 Python 层面的依赖这是最省心的组合。3.3 TensorRT 与模型中转YOLOv11 与 BeVFormerThor 的感知模型最终都要转成 TensorRT engine 部署而不是在 PyTorch 里直接跑。直接跑 PyTorch 推理延迟高、显存占用大不实用。YOLOv11ultralytics的导出很顺from ultralytics import YOLO model YOLO(yolov11n.pt) model.export(formatengine, device0)导出后的 engine 可以直接用 TensorRT 加载推理实测单帧 latency 比 PyTorch 低很多。这里要注意的是第一次导出 engine 时会有较长的构建时间需要保证 SWAP 充足。BeVFormer 环境配置则依赖地狱比较严重。它依赖 mmcv、mmdet3d、mmsegmentation 等一套 OpenMMLab 生态版本必须严格对齐。我当时用的组合大致是torch 1.13 或 2.0 系列mmcv-full 1.6.xmmdet3d 1.0.0rc6其中 mmcv 需要源码编译整个过程在 AGX Orin 上大约要一两个小时。编译失败大多是因为缺少依赖库或者版本不对建议编译前先确认前面第二章的 SWAP 已经配好否则很容易进程被杀。3.4 本地大模型扩展DeepSeek 等 LLM 的接入AGX Orin 64GB 版本有足够内存跑压缩后的 7B-14B 量级模型我们会把 DeepSeek 这类 LLM 用来做语音语义后端帮 Thor 理解自然语言指令。由于人形机器人系统内存还要给感知和控制预留我不建议直接加载全精度大模型。实际开发中用的是 ollama 等工具来做量化部署设置好上下文长度控制好显存分配。docker run -d --runtime nvidia --network host \ --name llm-server \ -v /mnt/ssd/ollama:/root/.ollama \ ollama/ollama把 LLM 跑在容器里有个好处不污染系统环境重启后状态干净出了问题直接销毁重建容器就行。这对边开发边调试的机器人项目来说是关键优势。4. 感知、控制与通信机器人侧中间件环境怎么搭4.1 ROS 2 的选择与 Docker 化取舍Thor 的软件栈使用 ROS 2 作为中间件。Jetson 上装 ROS 2 有两种思路直接装到系统里或者用 Docker 容器。我的建议是开发阶段用容器。原因是 Jeston 系统自带的 Python 环境和 ROS 2 的依赖经常冲突比如numpy版本、pybind11版本的问题直接装到系统里会让系统变得很脆弱。用 Docker 后系统层和 ROS 层就分开了坏了就重新拉镜像不用反复刷机。推荐使用 dustynv 的 jetson-containers 项目它所提供的 ROS 镜像预编译了 CUDA、cuDNN、PyTorch、TensorRT 等组件比自己从零组装省掉很多时间docker run -it --rm --runtime nvidia --network host \ dustynv/ros:humble-pytorch-l4t-r35.4.1 bash这个镜像内部已经包含 ROS 2 Humble、PyTorch、TensorRT 和 EGL 支持视觉相关话题传输和渲染效率比默认镜像高很多。长时间开发后你应该把最终环境 commit 成自己的镜像保证团队复现一致。4.2 目标检测与 BEV 感知的依赖地狱Thor 的感知任务分两块近处用 YOLOv11 做目标检测负责识别障碍物和抓取目标远处用 BeVFormer 这类 BEV 感知模型做鸟瞰视图重建服务于路径规划。YOLOv11 的环境相对简单只需要 ultralytics 包和 torch。但要注意导出 TensorRT engine 时模型的输入尺寸必须固定不固定的话导出速度会慢很多运行时 tensor shape 切换还会增加延迟。BeVFormer 的环境就复杂多了依赖的 mmcv 版本和 Python 版本咬得很紧。排查问题时第一步永远是检查版本矩阵组件版本CUDA11.8Python3.8PyTorch2.0.1mmcv-full1.6.2mmdet2.28.2mmdet3d1.0.0rc6版本差一个位数就会出现算子缺失或者维度对不上这类隐蔽错误。4.3 多传感器时间同步的几个现实方案Thor 同时带着双目相机、深度相机和 IMU多传感器时间同步是感知能否融合的关键。Jetson 平台本身没有传统 PC 上的独立采集卡所以需要软硬结合方案。首先硬件层面如果相机支持外部触发用 GPIO 脉冲做同步信号最靠谱其次软件层面在 ROS 2 里所有传感器消息统一打时间戳并通过主时钟同步ptp或ntp来校准板卡时钟和相机时钟。sudo timedatectl set-ntp true多路视频传输不要全走 TCPTCP 的背压机制会让图像帧延迟抖动。我的建议是视频流用共享内存或者 ZeroMQ 进行传输控制指令走 ROS 2 DDS。Jetson 的/dev/shm空间有限注意使用共享内存传输时调整sudo mount -o remount,size4G /dev/shm5. 远程开发环境VSCode、Pycharm 与多端口服务编排5.1 VSCode Remote-SSH 与 Pycharm 远程解释器Thor 板卡属于无头设备开发时必须在一台宿主机上远程连接。我用得最顺的是 VSCode Remote-SSH 和 Pycharm 远程解释器两者各有使用场景VSCode 适合快速改代码、看日志Pycharm 适合做 Python 代码的断点调试和 AI 项目重构。SSH 登录 Jetson 之前先把密钥拷过去省去每次输密码ssh-keygen -t ed25519 ssh-copy-id userjetson-ipVSCode 第一次连接 Jetson 时会在设备端安装 server 服务这一步偶尔会卡住多半是网络问题。建议在 devices 端手动下载对应版本的 vscode-server 压缩包解压到~/.vscode-server时间会节省很多。Pycharm 远程解释器则需要保证宿主机和 Jetson 的 Python 路径映射一致否则调试时源码路径会错乱。Node.js 服务我也在 Thor 上跑过比如机器人 WebUI 前端。强烈建议使用 nvm 安装而不是直接apt install nodejsapt 源里的版本往往太老跑现代前端项目会缺一堆兼容性依赖。curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash nvm install 205.2 Nginx 多端口反代与自定义域名Thor 同时跑着多个 Web 服务ROS Bridge 可视化面板端口 9090、FastAPI 后端端口 8000、前端 WebUI端口 3000、LLM 服务端口 11434。如果直接记端口号不仅容易混而且多个服务跨域问题也很麻烦。我在板卡上配置了 Nginx 作为统一入口按不同的子路径转发到对应端口同时启用自定义域名thor.local。这样只是调整 Nginx 配置不需要改各个服务的绑定端口server { listen 80; server_name thor.local; location /api/ { proxy_pass http://127.0.0.1:8000/; } location /webui/ { proxy_pass http://127.0.0.1:3000/; } location /bridge/ { proxy_pass http://127.0.0.1:9090/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } }在宿主机/etc/hosts里加上192.168.x.x thor.local浏览器里直接访问http://thor.local/webui/就通了。对于 WebSocket 的 ROS Bridge记得配置 Upgrade 相关 headers否则连接会自动断开。如果开发环境里有虚拟机和 Thor 在同一局域网又不想被虚拟机 NAT 挡住那需要将虚拟机网络模式改为桥接让虚拟机获得局域网独立 IPNginx 转发目标指向虚拟机的那个 IP 就行。5.3 日志、看门狗与一键巡检机器人跑起来后日志排查极其重要。Jetson 自带的journalctl和tegrastats是我最常用的两个命令。tegrastats可以实时查看 CPU、GPU、内存和温度sudo tegrastats --interval 1000为了让环境配置可复现也为了快速排查问题我写了一个简单的巡检脚本把环境状态一次性打印出来#!/bin/bash echo JetPack 版本 cat /etc/nv_tegra_release echo CUDA 版本 nvcc --version | grep release echo PyTorch python3 -c import torch; print(torch.__version__, torch.cuda.is_available()) echo 磁盘空间 df -h / /mnt/ssd echo 温度与功耗 sudo tegrastats --interval 1000 sleep 2; sudo kill $!这个脚本在每次系统异常后跑一遍能快速判断问题出在系统层还是 AI 层。环境配置过程中我把每一步都记录在这个脚本里更新系统不迷路。6. 性能模式、散热和故障复盘的“肌肉记忆”6.1 nvpmodel 与 jetson_clocks 的使用Jetson 默认运行在省电模式这让很多初次接触的人误以为板卡性能不行。实际上你需要先切换性能模式再压测。# 查看可用模式 sudo nvpmodel -q # 切换到 MAXN最高性能 sudo nvpmodel -m 0 # 锁定 CPU/GPU 最高频率 sudo jetson_clocks交互式开发期间我通常直接用 MAXN 模式确保编译和推理不被频率限制。不过 Thor 整机用电池供电时MAXN 模式的功耗太猛我会切换回 20W 模式来延长运行时间检测和规划在低功耗下也能跑得起来。这个切换被封装在 Thor 的电源管理节点里根据电池电量自动动态调整。6.2 刷机变砖恢复与 QSPI 芯片经验Jetson 刷机时如果中途断电、或者宿主机的 USB 断了偶尔会出现设备启动卡在 logo、甚至完全无法进入恢复模式的情况。Thor 开发的这几个月里我至少经历过三次这种变砖时刻。第一次是刷入错误的分区镜像设备完全无法启动第二次是刷机过程中拔了数据线导致 QSPI 分区表损坏。QSPI 是存放早期引导代码的地方一旦损坏设备连 USB 恢复模式都进不去。解决办法是重新让设备进入强制恢复模式按住板载的恢复键和重置键接上宿主机再用 SDK Manager 执行强制刷写。Orin Nano 系列如果 QSPI 芯片损坏还可能涉及更换芯片后重新烧写引导分区。这些操作需要对硬件熟手在场指导不建议新手自己贸然动手。注意我在后面的所有刷机操作里都养成了一个习惯——刷机前用dd备份当前系统的完整镜像存到大容量硬盘上。万一操作失误几分钟内就能恢复到之前的可用状态。6.3 散热与长期稳定运行的现实取舍Thor 的推理任务长时间高负荷运行时GPU 温度会持续升高如果不做处理系统会强制降频表现为帧率下降和延迟抖动。散热上我做了两件事一是主动风冷风扇策略调整为根据 GPU 温度动态调速而不是全速或停止二是给机壳留了足够的通风孔。两者配合下负载压测时核心温度控制在可接受范围内。# 风扇控制示例PWM 方式 echo 200 /sys/devices/pwm-fan/target_pwm长期运行的稳定性最终是靠三个东西保证的稳定的电源、有效的散热、干净的软件环境。任何一块拖后腿设备就会在日常运行里给你时不时来一次死机或者重启。这套环境从零到能跑通 Thor 的第一个端到端 Demo我前后完整清过三次系统中间返工最多的就是依赖版本的问题。后来我养成了一个习惯每配完一个环境、装完一组关键依赖就立刻打包一个 Docker 镜像或者备份整个系统分区而不是等所有东西配完再一次性备份。如果哪天系统崩了恢复到的那个环境状态跟崩之前完全一致不会出现系统救回来了但依赖全丢了的尴尬。最后再分享一个小经验板卡上所有环境相关的改动都记录下来跟代码库走版本管理。写清楚你改了什么、为什么改下次别人接手 Thor就不用从头开始踩你踩过的坑了。