ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

NiceGUI 与 ROS2 集成实战:为机器人构建基于 Web 的虚拟摇杆与位姿可视化界面

NiceGUI 与 ROS2 集成实战:为机器人构建基于 Web 的虚拟摇杆与位姿可视化界面 NiceGUI 与 ROS2 集成实战为机器人构建基于 Web 的虚拟摇杆与位姿可视化界面【免费下载链接】niceguiCreate web-based user interfaces with Python. The nice way.项目地址: https://gitcode.com/GitHub_Trending/ni/nicegui本指南基于 NiceGUI 官方仓库中的 ROS2 集成示例examples/ros2编写介绍如何把 NiceGUI 作为 ROS2 机器人的 Web 控制界面通过浏览器中的虚拟摇杆发布Twist速度指令由模拟器节点计算并回传Pose位姿再用 3D 场景实时渲染机器人运动轨迹。读完本文你将掌握 NiceGUI 节点与 ROS2 节点在同一进程内协同工作的架构、docker compose一键启动方式以及让 NiceGUI 支持热重载auto-reload的关键技巧并能够把示例代码移植到自己的 ROS2 工作空间中。一、示例概览NiceGUI 作为 ROS2 机器人的 Web 前端ROS2Robot Operating System 2本身并不包含图形用户界面机器人调试通常依赖rviz2等桌面工具。本示例展示了另一种思路用 NiceGUI 在浏览器中构建控制面板让用户通过http://127.0.0.1:8080即可操控一台虚拟移动机器人。整个系统由两个 ROS2 节点组成见 examples/ros2/ros2_ws/src节点包名职责NiceGUI 控制界面gui提供虚拟摇杆、速度显示和 3D 位姿可视化发布Twist指令简易模拟器simulator订阅cmd_vel速度指令按运动学模型积分计算新位姿并发布Pose数据流为闭环用户在页面上拖动摇杆 → NiceGUI 节点把Twist消息发布到cmd_vel话题 → 模拟器节点消费该指令、更新位姿 → 将Pose消息发布到pose话题 → NiceGUI 节点订阅pose并驱动界面上的滑块与 3D 场景刷新。整个链路全部基于标准的geometry_msgs消息不依赖任何自定义接口因此可以无缝替换为真实机器人的话题。从源码结构看ros2_ws/src下是两个标准的ament_python风格 ROS2 包gui与simulator每个包都包含package.xml、setup.py、setup.cfg与源码目录说明这并非一个玩具脚本而是一套符合 ROS2 工程规范的完整示例。二、快速启动一条命令跑通全部环境官方推荐方式是用 Docker 构建并启动命令如下在仓库根目录下操作cd examples/ros2 docker compose up --build构建过程会拉取 ROS2 Humble 基础镜像、安装 NiceGUI、编译工作空间启动完成后浏览器访问http://127.0.0.1:8080即可看到虚拟摇杆与可视化界面。页面交互方式为在蓝色摇杆区域内按住并拖动鼠标即可发布线速度与角速度指令松开鼠标后速度归零。docker-compose.ymlexamples/ros2/docker-compose.yml本身非常精简核心配置如下services: nicegui: build: context: . ports: - 8080:8080 volumes: - ./ros2_ws/src:/ros2_ws/src其中ports将容器内 NiceGUI 默认监听的 8080 端口映射到宿主机volumes把宿主机上的ros2_ws/src挂载进容器配合镜像构建时使用的colcon build --symlink-install符号链接安装使得在宿主机上修改 ROS2 包源码后无需重新构建镜像即可生效便于迭代开发。三、Docker 镜像构建细节从镜像到启动链路examples/ros2/Dockerfile 完整还原了环境搭建过程FROM ros:humble-ros-base RUN apt-get update apt-get install -y python3-pip rm -rf /var/lib/apt/lists/* SHELL [/bin/bash, -c] RUN pip3 install nicegui ADD ros2_ws /ros2_ws WORKDIR /ros2_ws RUN source /opt/ros/humble/setup.bash \ colcon build --symlink-install COPY ros_entrypoint.sh / EXPOSE 8080 ENTRYPOINT [/ros_entrypoint.sh] CMD ros2 launch gui main_launch.py关键点说明基础镜像ros:humble-ros-base示例基于 ROS2 Humble 发行版Ubuntu 22.04 对应的 LTS 版本。如果你的环境使用其他发行版如 Jazzy、Iron需要相应调整基础镜像与setup.bash路径。SHELL [/bin/bash, -c]确保source命令在 bash 下可用/bin/sh默认是 dash不支持source。colcon build --symlink-install以符号链接方式安装构建产物与上文docker-compose.yml的源码挂载配合实现改代码不重建镜像。CMD ros2 launch gui main_launch.py容器启动后通过 launch 文件同时拉起gui与simulator两个节点。启动入口脚本 examples/ros2/ros_entrypoint.sh 先加载 ROS2 与工作空间环境再执行传入命令#!/bin/bash set -e source /opt/ros/humble/setup.bash source install/setup.bash exec $四、核心源码解析NiceGUI 节点与模拟器节点4.1 NiceGUI 节点界面与 ROS2 在同一进程内协作examples/ros2/ros2_ws/src/gui/gui/node.py 是整个示例的灵魂。它定义了一个继承rclpy.node.Node的NiceGuiNode类在 ROS2 节点的构造函数中直接搭建界面class NiceGuiNode(Node): def __init__(self) - None: super().__init__(nicegui) self.pose_update Event() self.speed_update Event() self.cmd_vel_publisher self.create_publisher(Twist, cmd_vel, 1) self.subscription self.create_subscription(Pose, pose, self.pose_update.emit, 1) ui.page(/) def page(): ...值得注意的两个设计用 NiceGUI 的Event作为消息桥梁。ROS2 订阅回调无法直接操作界面元素涉及线程与事件循环因此代码把订阅回调指向self.pose_update.emit再由页面内通过self.pose_update.subscribe装饰的函数在 NiceGUI 事件循环中更新界面实现 ROS2 线程与 UI 线程的安全解耦。页面即节点构造的一部分。ui.page(/)定义根路由其中包含三块卡片Control控制ui.joystick(colorblue, size50, on_move..., on_end...)虚拟摇杆拖动时回调send_speed发布速度松手时归零Data数据两个只读滑块显示当前线速度与角速度slider_props readonly selection-colortransparent一个标签显示位置坐标Visualization可视化ui.scene(350, 300)3D 场景用scene.extrusion(prism, 0.4)把一个五边形轮廓拉伸成立体机器人模型见 examples/ros2/ros2_ws/src/gui/gui/node.py。速度发布逻辑node.pydef send_speed(self, x: float, y: float) - None: msg Twist() msg.linear.x x msg.angular.z -y self.speed_update.emit(msg) self.cmd_vel_publisher.publish(msg)这里把摇杆的纵向位移映射为linear.x线速度横向位移取反映射为angular.z角速度并同时更新界面滑块与发布Twist消息。位姿更新则用四元数的z/w分量通过2 * atan2(z, w)换算偏航角yaw驱动 3D 模型move与rotate。4.2 模拟器节点一个 10Hz 的简易运动学模型examples/ros2/ros2_ws/src/simulator/simulator/node.py 实现了一个最简单的差速/独轮运动学仿真class Simulator(Node): INTERVAL 0.1 def __init__(self) - None: super().__init__(simulator) self.pose_publisher_ self.create_publisher(Pose, pose, 1) self.subscription self.create_subscription(Twist, cmd_vel, self.handle_velocity_command, 1) ... self.timer self.create_timer(self.INTERVAL, self.update_pose)以INTERVAL 0.1秒10Hz周期定时器驱动位姿积分订阅cmd_vel缓存线速度linear.x与角速度angular.z每个周期按x v * cos(yaw) * dt、y v * sin(yaw) * dt更新位置并把 yaw 增量打包回四元数z sin(yaw/2)、w cos(yaw/2)后发布Pose。该节点对应的package.xmlexamples/ros2/ros2_ws/src/simulator/package.xml与gui包一样声明了对rclpy与geometry_msgs的依赖。4.3 Launch 文件一次启动两个节点examples/ros2/ros2_ws/src/gui/launch/main_launch.py 通过launch_ros同时拉起界面节点与模拟器节点def generate_launch_description(): return LaunchDescription([ Node( packagegui, executablenicegui_node, nameexample_gui, outputscreen, ), Node( packagesimulator, executablesimulator_node, nameexample_simulator, outputscreen, ), ])可执行文件名nicegui_node/simulator_node由各包的setup.py中entry_points注册例如 gui/setup.py 中的nicegui_node gui.node:main同时该文件还负责把launch目录安装为 ROS2 共享数据文件。五、关键技巧如何让 NiceGUI 节点支持热重载原文档特别强调本示例比超级最小示例复杂一点正是为了支持 NiceGUI 节点的自动重载auto-reloading。这个技巧集中在 gui/node.py 的末尾三行app.on_startup(lambda: threading.Thread(targetros_main).start()) ui_run.APP_IMPORT_STRING f{__name__}:app # ROS2 uses a non-standard module name, so we need to specify it here ui.run(uvicorn_reload_dirsstr(Path(__file__).parent.resolve()), favicon)拆解如下ROS2 入口与 NiceGUI 入口分离main()被刻意留空仅作为setup.py注册的 ROS2 控制台脚本入口这样ros2 run gui nicegui_node能正常找到可执行文件真正启动 ROS2 的逻辑在ros_main()中——rclpy.init()后创建节点并rclpy.spin(node)并用try/except ExternalShutdownException优雅处理外部关闭信号。用后台线程承载 ROS2 spinapp.on_startup(...)在 NiceGUI 应用启动时开启线程执行ros_main使rclpy.spin与 NiceGUI 的 uvicorn 事件循环并行运行互不阻塞。显式指定导入字符串由于 ROS2 使用非标准模块名gui.node而不是普通 Python 包名需要ui_run.APP_IMPORT_STRING f{__name__}:app告诉 NiceGUI 从哪里导入应用对象否则自动重载时 uvicorn 无法重新加载模块。限定重载目录ui.run(uvicorn_reload_dirs...)只监听gui/node.py所在目录的文件变化避免整个ros2_ws源码树含 ROS2 生成文件触发无谓重载favicon顺带把页面图标设为机器人 emoji。这样配置后修改gui/node.py保存NiceGUI 会自动重载而rclpy节点所在的线程会随应用重启重新初始化开发者无需每次改动都重建容器。六、移植到自己的 ROS2 项目原文档指出如果你想在本地或自己的 ROS2 工程中运行 NiceGUI 节点直接复制ros2_ws/src/gui目录下的代码即可。推荐移植步骤把gui包目录package.xml、setup.py、setup.cfg、gui/、launch/复制进你的src/工作空间在package.xml中确认依赖rclpy与geometry_msgs已声明修改setup.py中的控制台脚本入口与launch数据文件安装路径在main_launch.py中把你的真实机器人节点加入LaunchDescription并将话题名替换为机器人实际使用的cmd_vel/pose话题重新colcon build --symlink-install并source install/setup.bash运行ros2 launch gui main_launch.py。若在本地非 Docker运行前提是已安装 ROS2 Humble 与pip3 install nicegui并且记得先source /opt/ros/humble/setup.bash与source install/setup.bash后再启动 launch 文件。七、小结本示例展示了一条完整的ROS2 Web UI落地路径以 ROS2 标准消息Twist/Pose为契约把交互式 Web 界面与机器人逻辑封装在同一个 ROS2 节点中通过Event桥接 ROS2 回调线程与 NiceGUI 事件循环并利用app.on_startup后台线程、APP_IMPORT_STRING与uvicorn_reload_dirs三个配置实现开发期热重载。无论是驱动虚拟机器人做仿真验证还是把send_speed、位姿订阅替换为真实硬件的话题接口这套架构都可以直接复用——这也正是用 Python 以优雅的方式创建 Web 界面NiceGUI 项目定位在机器人领域的一个典型场景。【免费下载链接】niceguiCreate web-based user interfaces with Python. The nice way.项目地址: https://gitcode.com/GitHub_Trending/ni/nicegui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表