作为一名 Java 后端开发者,你是否想过用 Spring Boot 和 WebSocket 就能遥控一个机器人?本指南将带你从零开始,在虚拟机中安装 Ubuntu 22.04 和 ROS 2 Humble,并用你最熟悉的 Java 语言通过 rosbridge 实时读取机器人位姿、下发运动指令。无需深入学习 C++/Python,全程复制粘贴即可跑通。
目录
-
为什么选择 Ubuntu 22.04 + ROS 2 Humble?
-
第一步:下载 Ubuntu 22.04.5 镜像
-
第二步:在 VMware 中安装 Ubuntu 22.04
-
第三步:安装 VMware Tools 并更新系统
-
第四步:使用 fishros 一键安装 ROS 2 Humble
-
第五步:验证 ROS 2 环境------召唤小乌龟
-
第六步:安装 rosbridge------打通 Java 与 ROS 的桥梁
-
第七步:Java 客户端开发(Spring Boot 可选)
-
第八步:运行与调试
-
总结与下一步学习建议
1. 为什么选择 Ubuntu 22.04 + ROS 2 Humble?
| 对比项 | Ubuntu 24.04 + ROS 2 Jazzy | Ubuntu 22.04 + ROS 2 Humble |
|---|---|---|
| 默认显示服务 | Wayland(VMware 图形兼容性差) | X11(开箱即用,小乌龟必现) |
| 社区教程丰富度 | 较新,中文资料较少 | 全网教程最全(古月居等均基于 Humble) |
| 长期支持 | 标准支持至 2029 年 | 标准支持至 2027 年(足够学习) |
| 对 Java 开发者的友好度 | 需额外配置显示 | 零配置,专注代码 |
结论: 对于初学者,Ubuntu 22.04 + ROS 2 Humble 是当前最稳妥、省心的组合。
2. 第一步:下载 Ubuntu 22.04.5 镜像
推荐使用国内镜像站,下载速度快且稳定。
-
清华大学开源软件镜像站
https://mirrors.tuna.tsinghua.edu.cn/ -
中科大镜像站
https://mirrors.ustc.edu.cn -
阿里云镜像站 (若上述链接失效可尝试)
https://mirrors.aliyun.com
建议使用多线程下载工具(如 IDM、Free Download Manager)加速下载。
3. 第二步:在 VMware 中安装 Ubuntu 22.04
-
打开 VMware Workstation Pro,点击"创建新的虚拟机"。
-
选择 "典型(推荐)" → 下一步。
-
选择 "安装程序光盘映像文件",浏览并选中下载好的 ISO 文件。
-
客户机操作系统 选择 Linux ,版本选择 Ubuntu 64 位。
-
虚拟机名称随意(如
Ubuntu-ROS2),位置建议放在 SSD 分区。 -
磁盘大小建议 60 GB ,选择 "将虚拟磁盘存储为单个文件"。
-
点击 "自定义硬件" 进行关键配置:
-
内存 :分配 8 GB(若物理内存 ≥16 GB)。
-
处理器 :分配 4 个核心。
-
显示器 :勾选"加速 3D 图形" ,图形内存设为 1 GB。
-
网络适配器 :默认 NAT 模式(后续可改为桥接)。
-
-
完成创建,开启此虚拟机。
安装过程
-
语言选择 English(避免中文路径编码问题)。
-
安装类型选 "Erase disk and install Ubuntu"(仅影响虚拟磁盘)。
-
设置用户名和密码(例如用户名
dafu,密码自定)。 -
安装完成后点击 "Restart Now",按提示移除安装介质(虚拟机会自动处理)。
4. 第三步:安装 VMware Tools 并更新系统
VMware Tools 能让宿主机与虚拟机之间复制粘贴文本、拖拽文件,极大提升效率。
在终端(Ctrl+Alt+T)中执行:
bash
sudo apt update
sudo apt install open-vm-tools-desktop -y
sudo reboot
重启后,你可以在 Windows 和 Ubuntu 之间自由复制粘贴命令和代码。
5. 第四步:使用 fishros 一键安装 ROS 2 Humble
国内网络环境下,使用 fishros 脚本安装 ROS 2 是最简单的方式。
bash
wget http://fishros.com/install -O fishros && bash fishros
-
输入
1选择 "一键安装 ROS 2"。 -
选择
humble版本(输入对应序号)。 -
选择 "桌面版" (输入
1)。 -
等待安装完成(约 15~30 分钟),期间可能提示输入
Y确认。
安装完成后,关闭当前终端,重新打开一个新终端,让环境变量生效。
验证安装:
bash
ros2
若出现一大串 usage: ros2 ... 帮助信息,说明安装成功。
6. 第五步:验证 ROS 2 环境------召唤小乌龟
在终端中运行:
bash
ros2 run turtlesim turtlesim_node

如果弹出一个蓝色背景、中间有只小乌龟的窗口,恭喜你,ROS 2 环境完美运行!
若提示
Package 'turtlesim' not found,执行安装:
bashsudo apt install ros-humble-turtlesim
新开第二个终端,运行键盘控制节点:
bash
ros2 run turtlesim turtle_teleop_key
保持该终端激活,按键盘方向键即可控制乌龟移动。

7. 第六步:安装 rosbridge------打通 Java 与 ROS 的桥梁
rosbridge 将 ROS 2 的 DDS 通信协议转换为 WebSocket,使得 Java、Web 前端等语言能轻松接入 ROS 网络。
bash
sudo apt update
sudo apt install ros-humble-rosbridge-suite

启动 rosbridge WebSocket 服务(保持运行,不要关闭):
bash
ros2 launch rosbridge_server rosbridge_websocket_launch.xml
看到 [INFO] [rosbridge_websocket]: Rosbridge WebSocket server started on port 9090 即表示服务已就绪。

8. 第七步:Java 客户端开发(Spring Boot 可选)
现在,你可以在 Windows 的 IDEA 中编写 Java 代码,通过 WebSocket 连接虚拟机的 9090 端口,与 ROS 2 交互。
8.1 确认网络连通性
在 Windows 的 PowerShell 或 CMD 中执行:
bash
ping <虚拟机IP>
若虚拟机使用 NAT 模式 ,IP 通常为 192.168.xxx.xxx,可在虚拟机终端中用 ip a 查看。若 ping 不通,请将 VMware 网络适配器改为 桥接模式(虚拟机设置 → 网络适配器 → 桥接模式)。
8.2 创建 Maven 项目并添加依赖
XML
<dependencies>
<!-- WebSocket 客户端 -->
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.4</version>
</dependency>
<!-- JSON 解析 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
</dependencies>
8.3 编写 Java 客户端(订阅位姿 + 发送速度指令)
java
package org.admin.demoros;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
import java.util.Scanner;
/**
* @author:DaFu
* @date: 2026/4/21 14:28
*/
public class RosTelemetryClient extends WebSocketClient {
private final ObjectMapper mapper = new ObjectMapper();
public RosTelemetryClient(URI serverUri) {
super(serverUri);
}
@Override
public void onOpen(ServerHandshake handshake) {
System.out.println("✅ Connected to ROS bridge");
// 订阅乌龟位姿
String subscribePose = "{\"op\":\"subscribe\",\"topic\":\"/turtle1/pose\",\"type\":\"turtlesim/msg/Pose\"}";
send(subscribePose);
System.out.println("📡 Subscribed to /turtle1/pose");
// 声明我们将要发布 cmd_vel 话题
String advertiseCmd = "{\"op\":\"advertise\",\"topic\":\"/turtle1/cmd_vel\",\"type\":\"geometry_msgs/msg/Twist\"}";
send(advertiseCmd);
System.out.println("📢 Advertising /turtle1/cmd_vel publisher");
}
@Override
public void onMessage(String message) {
try {
JsonNode root = mapper.readTree(message);
if (root.has("msg") && root.has("topic")) {
String topic = root.get("topic").asText();
if (topic.equals("/turtle1/pose")) {
JsonNode msg = root.get("msg");
double x = msg.get("x").asDouble();
double y = msg.get("y").asDouble();
double theta = msg.get("theta").asDouble();
System.out.printf("🐢 Turtle Position -> x: %.2f, y: %.2f, angle: %.2f%n", x, y, theta);
}
}
} catch (Exception e) {
// 忽略解析错误
}
}
public void sendVelocity(double linearX, double angularZ) {
try {
ObjectNode msgNode = mapper.createObjectNode();
ObjectNode linear = mapper.createObjectNode();
linear.put("x", linearX);
linear.put("y", 0.0);
linear.put("z", 0.0);
ObjectNode angular = mapper.createObjectNode();
angular.put("x", 0.0);
angular.put("y", 0.0);
angular.put("z", angularZ);
msgNode.set("linear", linear);
msgNode.set("angular", angular);
ObjectNode publishNode = mapper.createObjectNode();
publishNode.put("op", "publish");
publishNode.put("topic", "/turtle1/cmd_vel");
publishNode.set("msg", msgNode);
send(publishNode.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("Connection closed");
}
@Override
public void onError(Exception ex) {
ex.printStackTrace();
}
public static void main(String[] args) throws Exception {
// 替换为你的虚拟机 IP
URI uri = new URI("ws://192.168.194.148:9090");
RosTelemetryClient client = new RosTelemetryClient(uri);
client.connect();
Thread.sleep(1000); // 等待连接建立
Scanner scanner = new Scanner(System.in);
System.out.println("Enter commands (w: forward, s: backward, a: turn left, d: turn right, q: quit):");
while (true) {
String input = scanner.nextLine();
if (input.equals("q")) break;
switch (input) {
case "w": client.sendVelocity(2.0, 0.0); break;
case "s": client.sendVelocity(-2.0, 0.0); break;
case "a": client.sendVelocity(0.0, 2.0); break;
case "d": client.sendVelocity(0.0, -2.0); break;
default: System.out.println("Unknown command");
}
Thread.sleep(500);
client.sendVelocity(0.0, 0.0); // 停止
}
client.close();
scanner.close();
}
}
8.4 运行与测试
-
虚拟机中保持以下服务运行:
-
终端1 :
ros2 run turtlesim turtlesim_node -
终端2 :
ros2 launch rosbridge_server rosbridge_websocket_launch.xml
-
-
在 IDEA 中运行
main方法。
控制台将实时打印乌龟坐标,输入 w/a/s/d 敲回车可遥控乌龟移动(你只需要在 IDEA 控制台的输入区域直接输入 w/a/s/d 然后按回车即可。 即使刷屏覆盖了你的输入字符,程序依然能接收到你的指令(因为 Scanner 在独立线程等待输入)。)。
9. 第八步:运行与调试
常见问题排查
| 现象 | 原因 | 解决方法 |
|---|---|---|
java.net.ConnectException: Connection refused |
网络不通或 rosbridge 未启动 | ① ping 虚拟机 IP;② 检查 rosbridge 终端是否有报错;③ 若使用桥接模式,临时关闭 Windows 防火墙测试 |
| 连接成功但无坐标输出 | 未正确订阅或乌龟未运动 | 在虚拟机中运行 ros2 topic echo /turtle1/pose 查看是否有数据;若无数据,用键盘控制乌龟动一下 |
| 发送指令后乌龟不动 | advertise 失败或消息格式错误 | 检查 rosbridge 终端输出,尝试注释掉 advertise 语句(rosbridge 通常能自动处理) |
10. 总结与下一步学习建议
你已掌握的技能
-
✅ 在 VMware 中安装 Ubuntu 22.04 并配置 3D 加速
-
✅ 使用 fishros 一键安装 ROS 2 Humble
-
✅ 运行 turtlesim 仿真并通过键盘控制
-
✅ 安装 rosbridge 并启动 WebSocket 服务
-
✅ 编写 Java 客户端订阅位姿、发布速度指令
本文所有代码均在以下环境测试通过:
-
*Windows 11 + VMware Workstation Pro 17*
-
Ubuntu 22.04.5 LTS
-
ROS 2 Humble
-
*Java 17 + Maven 3.8*