从 Ubuntu 22.04 到 ROS 2 Humble 完整环境搭建与 Java 控制指南

作为一名 Java 后端开发者,你是否想过用 Spring Boot 和 WebSocket 就能遥控一个机器人?本指南将带你从零开始,在虚拟机中安装 Ubuntu 22.04 和 ROS 2 Humble,并用你最熟悉的 Java 语言通过 rosbridge 实时读取机器人位姿、下发运动指令。无需深入学习 C++/Python,全程复制粘贴即可跑通。

目录

  1. 为什么选择 Ubuntu 22.04 + ROS 2 Humble?

  2. 第一步:下载 Ubuntu 22.04.5 镜像

  3. 第二步:在 VMware 中安装 Ubuntu 22.04

  4. 第三步:安装 VMware Tools 并更新系统

  5. 第四步:使用 fishros 一键安装 ROS 2 Humble

  6. 第五步:验证 ROS 2 环境------召唤小乌龟

  7. 第六步:安装 rosbridge------打通 Java 与 ROS 的桥梁

  8. 第七步:Java 客户端开发(Spring Boot 可选)

  9. 第八步:运行与调试

  10. 总结与下一步学习建议


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 镜像

推荐使用国内镜像站,下载速度快且稳定。

建议使用多线程下载工具(如 IDM、Free Download Manager)加速下载。


3. 第二步:在 VMware 中安装 Ubuntu 22.04

  1. 打开 VMware Workstation Pro,点击"创建新的虚拟机"。

  2. 选择 "典型(推荐)" → 下一步。

  3. 选择 "安装程序光盘映像文件",浏览并选中下载好的 ISO 文件。

  4. 客户机操作系统 选择 Linux ,版本选择 Ubuntu 64 位

  5. 虚拟机名称随意(如 Ubuntu-ROS2),位置建议放在 SSD 分区。

  6. 磁盘大小建议 60 GB ,选择 "将虚拟磁盘存储为单个文件"

  7. 点击 "自定义硬件" 进行关键配置:

    • 内存 :分配 8 GB(若物理内存 ≥16 GB)。

    • 处理器 :分配 4 个核心

    • 显示器勾选"加速 3D 图形" ,图形内存设为 1 GB

    • 网络适配器 :默认 NAT 模式(后续可改为桥接)。

  8. 完成创建,开启此虚拟机

安装过程

  • 语言选择 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. 输入 1 选择 "一键安装 ROS 2"

  2. 选择 humble 版本(输入对应序号)。

  3. 选择 "桌面版" (输入 1)。

  4. 等待安装完成(约 15~30 分钟),期间可能提示输入 Y 确认。

安装完成后,关闭当前终端,重新打开一个新终端,让环境变量生效。

验证安装:

bash 复制代码
ros2

若出现一大串 usage: ros2 ... 帮助信息,说明安装成功。


6. 第五步:验证 ROS 2 环境------召唤小乌龟

在终端中运行:

bash 复制代码
ros2 run turtlesim turtlesim_node

如果弹出一个蓝色背景、中间有只小乌龟的窗口,恭喜你,ROS 2 环境完美运行!

若提示 Package 'turtlesim' not found,执行安装:

bash 复制代码
sudo 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. 虚拟机中保持以下服务运行:

    • 终端1ros2 run turtlesim turtlesim_node

    • 终端2ros2 launch rosbridge_server rosbridge_websocket_launch.xml

  2. 在 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*

相关推荐
Wenzar_2 小时前
**元宇宙经济中的智能合约与数字资产:基于Solidity的NFT交易平台开发实践**随着元宇宙概念持续升
java·python·区块链·智能合约
Giggle12182 小时前
从零解构一套校园外卖系统:架构设计、技术选型与核心难点剖析
java·运维·微服务
一叶飘零_sweeeet2 小时前
Spring Boot 4.0:云原生 Java 开发的范式革命
java·spring boot·云原生
Devin~Y2 小时前
大厂 Java 面试实战:Spring Boot 微服务 + Redis 缓存 + Kafka 消息 + Kubernetes + RAG(小Y水货翻车记)
java·spring boot·redis·kafka·spring security·jwt·oauth2
朱一头zcy2 小时前
设计模式入门:简单认识单例模式、模板方法、工厂模式、装饰模式、动态代理
java·设计模式
tmacfrank2 小时前
Kotlin 协程十一 —— 协作、互斥锁与共享变量
java·开发语言·kotlin
D4c-lovetrain2 小时前
Linux个人心得28(OSI 7 层模型全解析)
linux·运维·网络
计算机安禾2 小时前
【Linux从入门到精通】第9篇:用户与权限管理(下)——数字法与粘滞位
linux·服务器·人工智能·面试·知识图谱