当前位置: 首页 > news >正文

【智能系统项目开发与学习记录】bringup功能包详解

前言

本项目机器人平台为幻尔智能ROS2机器人,本节开始会逐步拆解学习其示例代码,侵权即删。

一、bringup 包核心定位

在 ROS2 生态中,bringup 包是系统启动包,核心作用是「一键启动机器人全系统的核心功能」,避免手动逐个启动控制器、传感器、应用节点等繁琐操作。

1.1 bringup 包的典型内容

  • 总启动文件(.launch.py):统筹启动所有子模块(相机、雷达、控制器等)
  • 自检节点(如 startup_check.py):启动前检查硬件设备(麦克风、网卡等)是否正常
  • 配置文件:定义硬件参数、启动逻辑(如环境变量判断)
  • 依赖管理文件(package.xmlsetup.py):确保启动所需的依赖包已安装

二、核心文件逐行拆解

2.1 包身份与依赖配置:package.xml

package.xml 是 ROS2 包的「身份证」,告诉系统包的名字、依赖、维护者等信息,必须与 setup.py 同步

2.1.1 文件结构与关键标签
<?xml version="1.0"?>
<!-- XML 格式校验:确保文件符合 ROS2 规范 -->
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?><!-- 根标签:format="3" 是 ROS2 主流格式 -->
<package format="3"><!-- 1. 基础身份信息 --><name>bringup</name>          <!-- 包名:必须唯一,与 setup.py 一致 --><version>0.0.0</version>       <!-- 版本号:如 1.0.0(正式版)、0.1.0(测试版) --><description>一键启动机器人控制器、雷达、相机等核心功能</description>  <!-- 功能描述(替换 TODO) --><maintainer email="1270161395@qq.com">ubuntu</maintainer>  <!-- 维护者:名字+邮箱 --><license>Apache-2.0</license>  <!-- 许可证:ROS2 常用 Apache-2.0(开源可商用) --><!-- 2. 运行依赖:启动包必须的依赖 --><depend>rclpy</depend>        <!-- Python 节点依赖:rclpy 是 ROS2 Python 核心库 --><depend>controller</depend>    <!-- 依赖控制器包(示例:根据实际需求添加) --><depend>peripherals</depend>   <!-- 依赖外设包(相机、雷达等) --><!-- 3. 测试依赖:仅代码测试时需要 --><test_depend>ament_copyright</test_depend>  <!-- 检查版权声明 --><test_depend>ament_flake8</test_depend>     <!-- 检查 Python 代码格式 --><test_depend>python3-pytest</test_depend>   <!-- 运行 Python 测试用例 --><!-- 4. 编译类型导出:告诉系统如何编译该包 --><export><build_type>ament_python</build_type>  <!-- Python 包用 ament_python;C++ 包用 ament_cmake --></export>
</package>
2.1.2 关键注意事项
  • 包名(<name>)必须与 setup.py 中的 package_name 完全一致,否则编译失败
  • 运行依赖(<depend>)要写全:缺少依赖会导致启动时提示「找不到某个包」
  • 许可证(<license>)不可省略:避免开源法律风险,优先选 Apache-2.0

2.2 安装与可执行配置:setup.py

setup.py 是 Python 打包工具的配置文件,负责:① 安装 Python 代码和资源文件;② 生成终端可执行命令(如 startup_check)。

2.2.1 完整代码与注释
import os                           # 处理文件路径
from glob import glob               # 查找匹配文件(如所有 launch 文件)
from setuptools import find_packages, setup  # Python 打包核心工具package_name = 'bringup'  # 包名:必须与 package.xml 一致setup(name=package_name,version='0.0.0',                # 版本号:与 package.xml 同步# 1. 自动查找包内所有 Python 模块(排除 test 测试目录)packages=find_packages(exclude=['test']),# 2. 安装非 Python 资源文件(launch、config 等)data_files=[# 2.1 注册包到 ROS2 索引(必须)('share/ament_index/resource_index/packages', ['resource/' + package_name]),# 2.2 安装 package.xml 到系统目录('share/' + package_name, ['package.xml']),# 2.3 安装所有 launch 文件到 share/bringup/launch 目录(os.path.join('share', package_name, 'launch'), glob(os.path.join('launch', '*.*'))),# (可选)安装配置文件:如 config 目录下的参数文件# (os.path.join('share', package_name, 'config'), glob(os.path.join('config', '*.*'))),],# 3. 安装依赖:Python 打包工具必须install_requires=['setuptools'],zip_safe=True,  # ROS2 推荐 True:支持压缩安装# 4. 包元数据:与 package.xml 同步maintainer='ubuntu',maintainer_email='1270161395@qq.com',description='一键启动机器人核心功能',license='Apache-2.0',tests_require=['pytest'],  # 测试依赖# 5. 生成终端可执行命令(核心!)entry_points={'console_scripts': [# 格式:终端命令 = 模块路径:函数名# 示例1:启动自检节点:ros2 run bringup startup_check'startup_check = bringup.startup_check:main',# 示例2:启动总 launch 文件(可选):ros2 run bringup start_all# 'start_all = bringup.script.start_all:main',],},
)
2.2.2 核心功能解析
  • data_files 资源安装:确保 launchconfig 等文件夹被安装到系统目录(install/bringup/share/bringup/),否则启动时找不到 launch 文件。
  • entry_points 可执行命令:定义后,可通过 ros2 run bringup 命令名 运行节点(如 ros2 run bringup startup_check),本质是映射到 Python 模块的 main 函数。

2.3 系统总启动文件:bringup_launch.py

这是 bringup 包的「核心大脑」,负责根据环境变量判断路径、启动所有子模块(控制器、相机、雷达等)。

2.3.1 完整代码与注释
import os
from ament_index_python.packages import get_package_share_directory  # 获取包路径# 导入 Launch 核心类
from launch_ros.actions import Node
from launch.actions import ExecuteProcess, IncludeLaunchDescription, OpaqueFunction
from launch import LaunchDescription, LaunchService
from launch.launch_description_sources import PythonLaunchDescriptionSourcedef launch_setup(context):"""根据环境变量配置启动路径,返回所有要启动的节点/launch"""# 1. 读取环境变量:判断是「编译安装版」还是「源码版」compiled = os.environ.get('need_compile', 'False')  # 默认为 False(源码版)if compiled == 'True':# 编译安装版:从系统安装目录获取包路径controller_path = get_package_share_directory('controller')peripherals_path = get_package_share_directory('peripherals')app_path = get_package_share_directory('app')else:# 源码版:直接指定源码路径(开发调试用)controller_path = '/home/ubuntu/ros2_ws/src/driver/controller'peripherals_path = '/home/ubuntu/ros2_ws/src/peripherals'app_path = '/home/ubuntu/ros2_ws/src/app'# 2. 启动子模块:包含其他包的 launch 文件# 2.1 启动控制器(如电机控制)controller_launch = IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(controller_path, 'launch/controller.launch.py')))# 2.2 启动外设(深度相机 + 雷达)depth_camera_launch = IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(peripherals_path, 'launch/depth_camera.launch.py')))lidar_launch = IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(peripherals_path, 'launch/lidar.launch.py')))# 2.3 启动 Web 相关服务(rosbridge 用于 Web 通信,web_video 用于视频流)rosbridge_launch = ExecuteProcess(cmd=['ros2', 'launch', 'rosbridge_server', 'rosbridge_websocket_launch.xml'],output='screen'  # 输出日志到终端)web_video_node = Node(package='web_video_server',executable='web_video_server',output='screen')# 2.4 启动自检节点(来自 bringup 包)startup_check_node = Node(package='bringup',executable='startup_check',  # 对应 setup.py 中定义的命令output='screen')# 3. 返回所有要启动的组件(顺序即启动顺序)return [startup_check_node,    # 1. 先自检controller_launch,     # 2. 启动控制器depth_camera_launch,   # 3. 启动相机lidar_launch,          # 4. 启动雷达rosbridge_launch,      # 5. 启动 Web 服务web_video_node         # 6. 启动视频流服务]def generate_launch_description():"""ROS2 launch 标准入口:返回 LaunchDescription 对象"""return LaunchDescription([OpaqueFunction(function=launch_setup)  # 包装 launch_setup,支持 Python 逻辑])if __name__ == '__main__':# 直接运行该文件时启动(非必需,通常用 ros2 launch 命令)ld = generate_launch_description()ls = LaunchService()ls.include_launch_description(ld)ls.run()
2.3.2 关键功能拆解
  1. 环境变量判断(compiled:解决「开发时用源码路径,安装后用系统路径」的问题,通过 os.environ.get('need_compile') 读取环境变量,启动前可通过 export need_compile=True 切换模式。

  2. IncludeLaunchDescription:用于「嵌套启动其他包的 launch 文件」,避免在一个文件中写所有启动逻辑,模块化更强(如单独启动相机的 depth_camera.launch.py)。

  3. Node vs ExecuteProcess

    • Node:启动 ROS2 节点(需指定 package 和 executable);
    • ExecuteProcess:执行系统命令(如 ros2 launch rosbridge_server ...)。

2.4 系统自检节点:startup_check.py

自检节点是启动前的「硬件检查员」,负责检查设备(麦克风、网卡)是否正常,并用 ROS2 消息控制蜂鸣器 / OLED 显示信息。

2.4.1 核心功能与代码
#!/usr/bin/env python3
import os
import time
import rclpy
import psutil
import threading
from ros_robot_controller_msgs.msg import BuzzerState, OLEDState  # 自定义消息def check_mic():"""检查麦克风设备是否存在,存在则启动语音识别"""# 查看 /dev 目录下是否有 ring_mic 设备mic_exists = os.popen('ls /dev/ | grep ring_mic').read() == 'ring_mic\n'if mic_exists:os.system("ros2 launch xf_mic_asr_offline startup_test.launch.py")def get_wifi_info():"""获取 Wi-Fi SSID(从设备序列号生成)和 IP 地址"""# 1. 从设备树读取序列号(树莓派/嵌入式设备常用)with open("/proc/device-tree/serial-number", 'r') as f:serial = f.readlines()[0][-10:-1]  # 截取后10位序列号ssid = f'HW-{serial[:8]}'  # 生成 SSID(如 HW-12345678)# 2. 获取 wlan0 的 IP 地址ip = '0.0.0.0'for iface, addrs in psutil.net_if_addrs().items():if 'wlan0' in iface:for addr in addrs:if addr.family == 2:  # 2 代表 IPv4 地址ip = addr.addressbreakreturn ssid, ipdef main():# 1. 启动麦克风检查线程(不阻塞主逻辑)threading.Thread(target=check_mic, daemon=False).start()# 2. 初始化 ROS2 节点rclpy.init()node = rclpy.create_node('startup_check')# 3. 创建发布器:控制蜂鸣器和 OLEDbuzzer_pub = node.create_publisher(BuzzerState, '/ros_robot_controller/set_buzzer', 10)oled_pub = node.create_publisher(OLEDState, '/ros_robot_controller/set_oled', 10)# 4. 等待 5 秒(确保其他节点启动完成)time.sleep(5)# 5. 控制蜂鸣器响一声(频率1900Hz,响0.2秒)buzzer_msg = BuzzerState()buzzer_msg.freq = 1900buzzer_msg.on_time = 0.2buzzer_msg.off_time = 0.01buzzer_msg.repeat = 1buzzer_pub.publish(buzzer_msg)# 6. 在 OLED 显示 Wi-Fi 信息(第一行 SSID,第二行 IP)ssid, ip = get_wifi_info()oled_msg1 = OLEDState()oled_msg1.index = 1  # 第一行oled_msg1.text = f'SSID: {ssid}'oled_pub.publish(oled_msg1)time.sleep(0.2)  # 短暂延时避免消息拥堵oled_msg2 = OLEDState()oled_msg2.index = 2  # 第二行oled_msg2.text = f'IP: {ip}'oled_pub.publish(oled_msg2)# 7. 保持节点运行rclpy.spin(node)rclpy.shutdown()if __name__ == '__main__':main()

三、实际应用流程(学习 / 复习重点)

3.1 编译 bringup 包

  1. 进入 ROS2 工作空间(如 ros2_ws):
    cd ~/ros2_ws
    
  2. 编译(仅编译 bringup 包,速度更快):
    colcon build --packages-select bringup
    
  3. 加载环境变量(每次新终端都需执行):
    source install/setup.bash
    

3.2 启动 bringup 系统

  1. (可选)设置环境变量(切换编译 / 源码模式):
    export need_compile=False  # 源码模式(开发用)
    # export need_compile=True  # 编译安装模式(部署用)
    
  2. 启动总 launch 文件:
    ros2 launch bringup bringup_launch.py
    

3.3 验证启动结果

  1. 查看所有启动的节点:

    ros2 node list
    

    应包含 startup_checkcontroller_nodedepth_camera_node 等。

  2. 查看话题是否正常发布:

    ros2 topic list
    

    应包含 /ros_robot_controller/set_buzzer(蜂鸣器控制)、/camera/image_raw(相机图像)等。

  3. 检查机器人模型(若有):启动 RViz 并加载模型:

    rviz2
    
    • 添加 RobotModel 插件;
    • 设置 Fixed Frame 为 base_link
    • 若能看到模型,说明启动成功。

四、常见问题排查(复习 / 应用必备)

4.1 launch 文件启动失败

  • 问题 1:找不到某个 launch 文件排查:检查 setup.py 的 data_files 是否包含 launch 目录,确保 launch 文件已安装到 install/bringup/share/bringup/launch

  • 问题 2:环境变量 need_compile 未设置解决:启动前执行 export need_compile=False(源码模式)或 True(编译模式)。

4.2 节点无法运行(ros2 run bringup startup_check 报错)

  • 问题 1:startup_check 命令不存在排查:检查 setup.py 的 entry_points 是否正确定义 startup_check = bringup.startup_check:main,重新编译后重试。

  • 问题 2:缺少自定义消息包报错:from ros_robot_controller_msgs.msg import ... ImportError解决:在 package.xml 中添加依赖 <depend>ros_robot_controller_msgs</depend>,重新编译。

五、总结:bringup 包学习要点

  1. 核心定位:一键启动全系统,模块化管理子模块(控制器、传感器等)。
  2. 文件分工
    • package.xml:管依赖和身份;
    • setup.py:管安装和可执行命令;
    • *.launch.py:管启动逻辑;
    • startup_check.py:管硬件自检。
  3. 应用关键:编译后必须 source 环境变量,启动时注意环境变量 need_compile 的模式切换。
  4. 排查思路:先看节点是否启动(ros2 node list),再看话题是否正常(ros2 topic list),最后定位具体模块问题。
http://www.dtcms.com/a/470486.html

相关文章:

  • 外贸网建站建公司网站的详细步骤
  • 美食网站建设书成都seo技术
  • 江河建设集团有限公司网站梧州网站建设流程
  • 在Qt中使用VTK
  • 正安北郊湖吉他文化广场自动化监测
  • 【论文阅读】DSPy-based neural-symbolic pipeline to enhance spatial reasoning in LLMs
  • cn域名后缀网站163企业邮箱格式
  • psql常用命令
  • 高速公路自动车道保持系统原理与实现
  • 番禺做网站最便宜的哪家公司wordpress注册界面
  • 【推荐100个unity插件】将您的场景渲染为美丽的冬季风景——Global Snow 2
  • Windows安装Elasticsearch保姆级教程
  • 温州网站链接怎么做在山东省建设监理协会网站
  • C++中的父继子承:继承方式实现栈及同名隐藏和函数重载的本质区别, 派生类的4个默认成员函数
  • 32.渗透-.Kali Linux-工具-netcat的说明
  • Large Kernel Modulation Network for Efficient Image Super-Resolution 学习笔记
  • 城乡住房建设部网站杭州市萧山区哪家做网站的公司好
  • 高精度逆向工程:XTOM蓝光扫描仪赋能自由曲面微尺寸共性电路的增材制造
  • 多区域主动-主动(PostgreSQL 逻辑复制 + 冲突解决)在 ABP 的落地
  • 东莞精密机械制造工厂如何10个SolidWorks共用一台服务器资源
  • 六盘水市住房和城乡建设局网站wordpress 淘宝客app
  • Google 智能体设计模式:推理技术
  • 恒丰建设集团有限公司 网站嘉兴提高网站排名
  • 奥远网站建设流程怎做不下网站刷枪
  • VBA即用型代码手册:保存为PDF文件SaveAs PDF
  • 【环境配置】Windows上安装(升级)Cuda11.6 + cudnn9.8 + pytorch 并测试
  • 国内网页设计网站建设建立wordpress网站吗
  • 400电话网络推广微信网站推广方法视频
  • Memcached append 命令详解
  • [Android soong构建系统]实例:定制化编译某个模块