☰
宇树G1开发环境搭建:SSH远程连接与VSCode配置实战
2026/9/27 6:21:34 网站建设 项目流程

1. 拿到G1之后,为什么第一件事是打通SSH而不是急着跑Demo

刚拿到宇树G1的开发者,十有八九会先翻官方文档找运动控制例程,恨不得十分钟内就让机器人站起来走两步。但真正在项目里摸爬滚打过的人都知道,在机器人本体上直接插显示器键鼠调试,是一件极其折磨人的事——G1的算力单元通常藏在机身内部,接口位置刁钻,你不可能每次都趴在地上接HDMI。所以我的习惯是:新机器到手,先不碰任何业务代码,集中精力把SSH远程通道打通,把VSCode远程开发环境搭起来。这一步做扎实了,后面所有调试都是坐在自己工位上完成的。

SSH(Secure Shell)在这里扮演的角色,本质上是给你的开发机和G1之间修一条加密隧道。你在这头敲命令,那头执行,输出再传回来。听起来简单,但G1这类机器人平台的网络环境有几个特殊之处:它可能跑的是定制Linux(不少国产机器人用的是openEuler或麒麟系),网络配置方式和你在Ubuntu上熟悉的netplan完全不是一回事;它可能默认没有图形界面,你连IP都不知道;它的网口可能只有一个,还和内部通信复用。这些坑我几乎全踩过一遍,所以这篇就把从IP配置到VSCode远程开发的完整链路拆开讲,重点放在那些文档里不会写、但实际一定会遇到的问题上。

这篇文章适合三类人:刚拿到G1准备做二次开发的工程师、被机器人网络配置卡住的中级开发者、以及想把自己调试流程规范化的团队。我会尽量把每一步的“为什么”讲清楚,而不是只丢一串命令让你抄。毕竟机器人这东西,环境一变,抄来的命令大概率跑不通,理解原理才能自己排错。

2. 先搞清楚G1的网络家底:接口、系统与默认状态

2.1 G1常见的网络接口形态与对应策略

宇树G1不同批次和配置,网络接口的形态不完全一样。我接触过的机器里,主要有这么几种情况:机身带一个RJ45千兆网口、通过USB转网口扩展、或者干脆只有WiFi模块。你得先确认自己手上这台是哪种,因为这直接决定了你的连接策略。

如果机身有原生RJ45网口,那是最省事的,一根网线直连你的开发机或者接到同一台交换机上就行。但要注意,很多机器人出厂时这个网口是配置成DHCP自动获取的,你根本不知道它拿到了什么IP。这时候有两个办法:一是登录路由器后台看DHCP租约列表,找到对应MAC地址的条目;二是用arp-scan或者nmap扫一遍局域网。我一般用后者,命令是sudo nmap -sn 192.168.1.0/24,扫完看哪个IP的MAC地址前缀和机器人网口对得上。

如果只有WiFi,那事情会麻烦一点,因为你要先让机器人连上你的网络。有些G1出厂会开一个热点,你用手机或电脑连上去,然后通过默认网关地址(通常是192.168.4.1或192.168.12.1这类)访问它的配置页面。但更常见的情况是,它根本没开热点,你得通过串口或者机身屏幕去配WiFi。这就引出了下一个问题:系统是什么。

2.2 openEuler与麒麟系系统的网络配置差异

G1的算力单元跑的系统,我见过openEuler、银河麒麟V10、也有Ubuntu 20.04的。这三个系统的网络配置方式差别不小,尤其是前两个国产系统,很多开发者不熟悉,容易在这里卡住。

openEuler用的是NetworkManager或者systemd-networkd,具体看版本。你可以先用nmcli device status看看网络管理工具是哪个。如果是NetworkManager,配置静态IP的命令是:

nmcli con mod "有线连接 1" ipv4.addresses 192.168.1.100/24 nmcli con mod "有线连接 1" ipv4.gateway 192.168.1.1 nmcli con mod "有线连接 1" ipv4.dns "8.8.8.8,114.114.114.114" nmcli con mod "有线连接 1" ipv4.method manual nmcli con up "有线连接 1"

注意连接名称要用nmcli con show查出来的实际名称,别照抄“有线连接 1”。麒麟V10也类似,但它有时候会用自己的一套网络配置工具,图形界面下好办,命令行下还是走nmcli居多。

这里有个坑我踩过:openEuler某些版本默认没装NetworkManager,用的是systemd-networkd。这时候你得去改/etc/systemd/network/下面的.network文件,格式和netplan完全不同。判断方法很简单,systemctl status NetworkManager看服务在不在跑,不在的话大概率就是networkd。

2.3 没有显示器和IP时,怎么摸进后台

这是最让人头大的场景:机器人没接显示器,你也不知道它IP,网络配置还是错的。这时候别慌,有几条路可以走。

第一条路是串口。G1的算力单元通常引出了调试串口(UART),你用USB转TTL线接上,波特率一般是115200,用screen /dev/ttyUSB0 115200或者minicom就能进控制台。进去之后用ip addr看网口状态,用nmcli或直接改配置文件都行。这是最可靠的方式,因为不依赖网络。

第二条路是网线直连加抓包。你把开发机和G1用网线直连,开发机设一个同网段的静态IP,然后tcpdump抓包看G1有没有发ARP或者DHCP请求。如果它在发DHCP Discover,说明它想自动获取IP,你可以在开发机上临时起一个DHCP服务给它分配地址。这招稍微绕,但应急时管用。

第三条路是看机身有没有USB接口能接键盘,有些G1预留了USB口,你插个键盘盲操也行,但没显示器还是看不到输出,所以基本不实用。综合下来,串口是首选,建议拿到机器第一件事就是确认串口线序和波特率,把它当成保底通道。

3. 静态IP配置:让G1的地址固定下来

3.1 为什么必须配静态IP而不是依赖DHCP

DHCP方便是方便,但对机器人开发来说是个隐患。你想想,你今天连上去调好了代码,明天开机IP变了,VSCode的远程连接配置全得改,脚本里的地址也得跟着换,烦不烦?更麻烦的是,如果你写了自动化部署脚本,IP一变直接全挂。所以只要这台G1是固定放在实验室或工位上用的,静态IP是必须的。

配静态IP还有个好处:你可以把IP规划进自己的网段体系。比如我习惯把机器人放在192.168.1.200-192.168.1.250这个区间,开发机用100-150,网关和路由器用1-10。这样一看IP就知道是什么设备,排查问题快很多。

3.2 openEuler下配置静态IP的完整流程

假设你已经通过串口或临时连接进了系统,现在要配静态IP。先确认网口名称:

ip link show

输出里类似enp3s0、eth0、enx00e04c680xxx的就是网口名。记住它,下面要用。

如果用NetworkManager,按2.2节里的nmcli命令走就行。但我要补充几个细节:ipv4.dns可以配多个,用逗号隔开;ipv4.method manual这步千万别漏,否则前面配的地址不生效;改完之后用nmcli con up重新激活连接,或者nmcli con reload再up。

如果用systemd-networkd,创建或编辑/etc/systemd/network/10-static.network:

[Match] Name=enp3s0 [Network] Address=192.168.1.200/24 Gateway=192.168.1.1 DNS=8.8.8.8 DNS=114.114.114.114

然后systemctl restart systemd-networkd,再用networkctl status enp3s0确认地址生效。

这里有个容易忽略的点:openEuler的防火墙默认可能是开着的,你配好IP但SSH连不上,先别怀疑网络,查一下防火墙。firewall-cmd --list-all看看ssh服务有没有放行,没有的话firewall-cmd --add-service=ssh --permanent && firewall-cmd --reload。

3.3 麒麟V10配置双IP的注意事项

有些项目需要G1同时接入两个网络,比如一个连控制网、一个连数据网,这就涉及配双IP。麒麟V10下可以用nmcli给同一个网口加多个地址:

nmcli con mod "有线连接 1" +ipv4.addresses 192.168.2.200/24

注意那个+号,表示追加而不是覆盖。加完之后重新激活连接。但这里有个坑:两个网段的网关不能冲突,你只能给一个网段配默认网关,另一个网段要么走静态路由,要么就不配网关只做直连通信。我见过有人两个网段都配了网关,结果路由表乱了,两个网络都时通时断。

另外麒麟V10对SELinux的管理比较严,如果你改了网络配置文件后服务起不来,看看/var/log/audit/audit.log里有没有SELinux拒绝记录,有的话用ausearch -m avc -ts recent查详情,必要时调整策略或临时设成permissive排查。

4. SSH服务端配置:让G1接受远程连接

4.1 确认SSH服务状态与放行端口

IP配通了,下一步是确保G1上的SSH服务在跑。systemctl status sshd看一眼,没跑就systemctl start sshd并systemctl enable sshd设成开机自启。然后确认监听端口,默认22,但有些定制系统会改。ss -tlnp | grep ssh能看到实际端口。

如果服务在跑但连不上,按这个顺序查:防火墙有没有放行、/etc/ssh/sshd_config里PermitRootLogin和PasswordAuthentication的设置、以及有没有AllowUsers限制。我遇到过一台G1,出厂配置里AllowUsers只允许一个特定用户,你用别的账号怎么都连不上,改成允许你的用户或者注释掉这行才行。

4.2 密钥登录配置:比密码安全且省事

密码登录每次都要输,而且脚本里嵌密码不安全。配密钥登录是一劳永逸的事。在开发机上生成密钥对:

ssh-keygen -t ed25519 -C "g1-dev"

一路回车,默认存在~/.ssh/id_ed25519。然后把公钥推到G1上:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@192.168.1.200

如果ssh-copy-id不可用,就手动把公钥内容追加到G1的~/.ssh/authorized_keys里。注意权限:.ssh目录必须是700,authorized_keys必须是600,权限不对SSH会拒绝使用密钥。这个坑在Windows上尤其常见,如果你把密钥文件放在NTFS分区,权限继承会出问题,报错类似bad owner or permissions on .../.ssh/config。解决办法是把密钥放到WSL或者用icacls手动改权限。

配好之后测试ssh user@192.168.1.200,能免密进去就成功了。然后建议把sshd_config里的PasswordAuthentication改成no,只留密钥登录,安全性提升一大截。

4.3 用主机名代替IP:配置SSH config

每次输IP也烦,可以在开发机的~/.ssh/config里加一段:

Host g1 HostName 192.168.1.200 User ubuntu IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 60

之后直接ssh g1就能连。ServerAliveInterval 60是防止连接空闲被断开,机器人调试时经常挂着连接去干别的,这个参数很实用。如果你有多台G1,就配多个Host条目,名字区分开,比如g1-arm、g1-base。

5. VSCode远程开发环境搭建:把IDE搬到G1上

5.1 Remote-SSH插件的安装与连接

VSCode远程开发的核心是Remote-SSH插件。在扩展市场搜“Remote - SSH”装上,然后按F1输入“Remote-SSH: Connect to Host”,选你配好的g1,VSCode会在G1上自动安装vscode-server。第一次连接会慢一点,因为要下载server组件,如果G1不能直连外网,你得手动下载vscode-server的离线包传上去。

连接成功后,VSCode左下角会显示“SSH: g1”,这时候你打开的任何文件夹、终端、调试会话都是在G1上执行的。这意味着你可以在本地VSCode里写Python代码,直接调用G1上的机器人SDK,断点调试也在G1上跑,体验和本地开发几乎一样。

这里有个网络细节:VSCode Remote-SSH默认走22端口,如果你改了SSH端口,在config里加Port 2222这样的配置就行。另外如果G1和开发机之间网络延迟高,VSCode的响应会有点卡,建议在config里加Compression yes开启压缩,能改善不少。

5.2 在远程环境里配Python和C++开发环境

G1的二次开发通常涉及Python(调SDK)和C++(性能敏感部分)。远程连上后,Python环境建议用conda或venv隔离,别直接动系统Python。python3 -m venv ~/g1-env && source ~/g1-env/bin/activate,然后在VSCode里选这个解释器。

C++的话,装C/C++扩展,配c_cpp_properties.json里的includePath指向G1上的SDK头文件目录。编译用CMake的话,在远程终端里跑cmake和make,VSCode的终端本身就是远程的,所以直接操作就行。调试配置写在.vscode/launch.json里,program路径填G1上的可执行文件路径,miDebuggerPath填G1上的gdb路径。

我建议把.vscode目录也纳入版本管理,这样团队里每个人连上同一台G1后,开发环境配置是一致的,省得各自配一遍还配出差异。

5.3 远程开发中常见的连接中断与重连处理

机器人调试时,G1可能会因为各种原因重启或者网络抖动,VSCode远程连接就断了。这时候别急着重启VSCode,先看右下角有没有“Reconnect”按钮,有的话点一下通常能恢复。如果不行,F1输入“Remote-SSH: Kill VS Code Server on Host”清掉服务端残留,再重连。

更彻底的办法是在SSH config里加ServerAliveInterval 30和ServerAliveCountMax 3,让客户端定期发心跳,减少被中间网络设备断开的概率。如果G1经常重启,可以考虑写个systemd服务让vscode-server开机自启,不过这个稍微复杂,一般用不到。

6. 那些文档不会告诉你的踩坑实录

6.1 SSH连接超时但ping得通:防火墙与路由的排查链路

这个现象很迷惑:ping 192.168.1.200通,但ssh就是超时。我遇到过好几次,排查下来原因各不相同。

第一次是G1的防火墙拦了22端口,但ICMP放行了,所以ping通SSH不通。firewall-cmd --list-all一看,ssh服务确实没在allowed列表里。加上就好了。

第二次更隐蔽:G1配了双网卡,默认路由走的是另一个网段,你从开发机来的包能到G1,但G1的回包走了错误的网口,导致TCP握手完不成。用ip route get 192.168.1.100看G1认为去开发机的路由走哪个网口,如果不是你期望的那个,就得调整路由优先级或者加策略路由。

第三次是中间交换机做了端口隔离,同一交换机下的两个口不能互通。这种就得换口或者改交换机配置。排查这类问题,tcpdump是你的好朋友,在G1上tcpdump -i any port 22,看有没有收到SYN包,收到了有没有回SYN-ACK,一步步缩小范围。

6.2 密钥登录报权限错误的根因与修复

bad owner or permissions on ~/.ssh/config这个报错,Windows、Mac、Linux上都可能出现,根因都是文件权限不符合SSH的严格要求。Linux/Mac下chmod 600 ~/.ssh/config && chmod 700 ~/.ssh就行。Windows下如果用的是OpenSSH,它检查的是NTFS ACL,你得用icacls命令把权限收紧到只有当前用户可读写。

还有一种情况是密钥文件本身权限太开,比如从U盘拷过来默认是777,SSH会拒绝使用。chmod 600 id_ed25519解决。我建议养成习惯,密钥文件生成后立刻改权限,别等报错了再查。

6.3 G1重启后IP丢失或SSH服务未自启的预防

有些G1重启后静态IP没了,变回DHCP。这通常是NetworkManager的连接配置没设成autoconnect,或者配置文件写错了位置。nmcli con show看连接的autoconnect是不是yes,不是的话nmcli con mod "有线连接 1" connection.autoconnect yes。

SSH服务没自启就是systemctl enable sshd没做。这两个问题都属于“配的时候好好的,重启就废”,建议配完网络和SSH后,主动重启一次G1验证,别等到正式跑实验时才发现。

7. 把这套流程固化成团队规范

一个人调通不算本事,让团队里每个人拿到G1都能快速上手才是价值。我的做法是写一份内部checklist,包含:串口线序和波特率、静态IP规划表、SSH密钥分发流程、VSCode远程配置模板。新机器到手,照着checklist走一遍,半小时内就能进入开发状态。

另外建议把G1的网络配置和SSH配置做成脚本,放在版本库里。新机器或者重装系统后,跑一遍脚本就恢复环境。脚本里注意把IP、主机名这些变量抽出来,不同机器用不同的配置文件覆盖,别硬编码。

最后分享一个我自己的习惯:每台G1的机身或者包装上贴一张标签,写上主机名、静态IP、SSH端口、串口波特率。别小看这张标签,实验室里机器一多,没有它你根本分不清哪台是哪台,每次都要重新查,浪费时间。这套流程跑顺之后,你会发现机器人开发的大部分时间都花在算法和业务上,而不是和环境搏斗。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询