1. 项目概述为什么单臂机械臂仿真必须从 MoveIt Gazebo 联合入手你刚买回一台 UR5e 或者自己搭了一台基于 ROS 的六自由度单臂机械臂手头只有几份 PDF 教程和一个空荡荡的 Ubuntu 终端。这时候最常遇到的问题不是“怎么写逆运动学”而是——“我的机械臂模型在 Gazebo 里一加载就抖关节乱飞连基本的静止都做不到”或者“MoveIt 启动后 Rviz 显示模型正常但 Plan 按钮灰着点不动终端疯狂刷出No IK solution found”更常见的是“Gazebo 界面一直在闪鼠标一移过去就卡顿GPU 占用飙到 95%根本没法调试轨迹”。这些不是玄学是单臂机械臂仿真平台搭建中必然踩过的三道门槛模型动力学不闭环、运动规划器与仿真器未对齐、仿真环境资源调度失衡。而 MoveIt Gazebo 这套组合恰恰是目前 ROS 生态中唯一能同时覆盖“高保真物理仿真”“工业级运动规划”“可视化调试闭环”的成熟路径。它不是玩具而是工业机器人算法验证的第一道真实防线——UR、Franka、KUKA 官方支持包全基于此架构ROS 2 Humble/Jazzy 中的ros2_controlgazebo_ros2_control插件链也完全延续这一范式。我带过 7 个高校机器人实验室发现新手最容易陷入两个误区一是把 Gazebo 当成“3D 展示器”只加载.sdf模型却不配置关节传动、摩擦、碰撞属性二是把 MoveIt 当成“自动规划黑箱”跳过 SRDF 配置、虚拟关节定义、规划组划分等底层约束建模。结果就是仿真跑得欢一上真机就撞墙。这篇文章不讲概念只拆解你打开终端后要敲的每一行命令背后的物理意义、参数取舍逻辑、以及我亲手调通 12 套不同构型单臂UR3/UR5e/Panda/ABB IRB120/自研 SCARA积累下来的硬核经验。如果你的目标是让机械臂在仿真中真正“像人一样思考并执行”而不是仅仅“转几个关节”那接下来的内容就是你绕不开的实操地图。2. 核心设计思路为什么必须用 MoveIt 做规划、Gazebo 做仿真而非其他组合2.1 MoveIt 不是“可选插件”而是单臂运动规划的事实标准很多人问“为什么不用 ROS 2 自带的nav2或者自己写 A* 算法做机械臂路径规划”答案很直接运动学约束不可降维。nav2是为二维平面移动底盘设计的它的代价函数只考虑距离、障碍物、转向角而单臂机械臂的规划空间是 6~7 维的关节空间C-space每一度旋转都牵涉雅可比矩阵、奇异点规避、末端姿态耦合。MoveIt 的核心价值在于它把这套高维约束封装成了可配置的模块IKFast 插件编译生成 C 级别逆解器求解速度比数值法快 200 倍以上UR5e 在 i5-8250U 上单次求解仅需 0.8msOMPL 规划器集成RRTConnect、PRMstar 等算法针对 C-space 特性做了采样优化比如RRTConnectkConfigDefault会自动在关节极限附近增加采样密度Collision Checking 分层机制先用简化包围盒OBB快速剔除明显碰撞再用精确三角面片Triangle Mesh校验关键帧平衡精度与实时性。我实测过纯 Python 实现的 RRT在 Panda 机械臂上规划一条避障抓取路径平均耗时 4.2 秒而 MoveIt OMPL 的RRTConnect在同等硬件下稳定在 0.35 秒内。这不是代码优化问题是数学模型层面的代差。所以当你看到panda_moveit_config或ur5e_moveit_config这类包名时它们本质是一套预验证的约束配置集包含SRDF 文件中定义的规划组planning group、允许的关节运动范围、末端执行器链接eef_link、虚拟关节virtual joint绑定关系。跳过这一步直接写move_group.plan()等于让汽车没有方向盘就上高速。2.2 Gazebo 不是“3D 渲染器”而是物理引擎与 ROS 的协议桥接器另一个常见误解是“Gazebo 就是画个 3D 模型加点纹理就行”。错。Gazebo 的核心是ODEOpen Dynamics Engine或 Bullet 物理引擎它负责实时解算牛顿-欧拉方程。一个 UR5e 模型在 Gazebo 中能否稳定站立取决于你是否正确设置了inertial参数质量mass、质心origin、惯性张量ixx/iyy/izz/ixy/ixz/iyz。很多开源 URDF 直接把mass1.0写死导致重力矩计算错误关节伺服器输出力矩过大而震荡joint传动模型transmission标签定义电机-减速器-关节的力矩传递关系hardwareInterface指定 ROS 控制接口类型PositionJointInterface还是EffortJointInterfacegazebo扩展标签damping阻尼系数、friction库伦摩擦、selfCollide自碰撞检测开关。UR5e 的肩部关节若damping0.0仿真中会出现高频抖动实测将damping设为0.5可完全抑制。更重要的是Gazebo 通过gazebo_ros_pkgs提供了三类关键 ROS 接口gazebo_ros_state_publisher将 Gazebo 中的关节状态position/velocity/effort以/joint_states形式发布gazebo_ros_control接收/cmd_vel或/position_controller/command等 topic转换为 ODE 引擎可理解的力矩指令gazebo_ros_p3d提供机器人在仿真世界中的全局位姿/ground_truth/state用于 SLAM 或导航验证。这意味着Gazebo 不是独立运行的 3D 程序而是 ROS 图ROS Graph中的一个节点。当你运行roslaunch ur5e_gazebo ur5e_world.launch时实际启动的是一个嵌入了 ROS 通信能力的 ODE 实例。这也是为什么ros2 launch gazebo_ros gazebo.launch.py必须指定world和gz_args参数——它在启动物理引擎的同时也在初始化 ROS 节点上下文。2.3 为什么不能用 Wokwi、AFSIM 或 Ignition Gazebo 替代网络热词里频繁出现的 WokwiArduino 仿真、AFSIM美军战术仿真、Ignition GazeboGazebo Next常被拿来对比。但它们与 MoveItGazebo 的定位根本不同Wokwi面向微控制器的数字电路级仿真无刚体动力学无法建模机械臂关节摩擦、齿轮间隙、电机响应延迟AFSIM聚焦于大尺度作战系统飞机、导弹、雷达其物理模型精度在厘米级而机械臂抓取要求亚毫米级位姿控制且不提供 ROS 接口Ignition Gazebo虽是 Gazebo 的下一代但截至 2024 年中其 ROS 2 支持仍处于实验阶段ign_ros2_control未进入 ROS 2 Humble 官方仓库社区维护的ros_ign包对 URDF 解析存在兼容性问题例如gazebo referencejoint_name标签会被忽略导致传动模型失效。我曾用 Ignition Gazebo 测试 Panda 机械臂结果发现gazebo_ros2_control插件加载后所有关节的effort值恒为 0排查三天才发现是ign-msgs版本与ros2-control的hardware_interface接口不匹配。而经典 Gazebo 9ROS 1 Noetic和 Gazebo 11ROS 2 Foxy/Humble经过十年迭代其gazebo_ros_pkgs已形成稳定 ABIur_description、panda_description等官方包均通过 CI 全流程测试。选择它不是守旧而是为稳定性支付的合理技术债。3. 核心细节解析URDF/SRDF 配置、Gazebo 插件绑定、MoveIt 配置三者的强耦合关系3.1 URDF 文件机械臂的“物理身份证”每个标签都在定义真实世界的约束URDFUnified Robot Description Format不是简单的 3D 模型描述它是机械臂在仿真中行为的宪法。一个典型的 UR5e 关节定义如下link nameshoulder_link inertial mass value5.2 / origin xyz0.01 -0.02 0.15 rpy0 0 0 / inertia ixx0.025 iyy0.022 izz0.018 ixy0.001 ixz-0.002 iyz0.001 / /inertial visual geometry mesh filenamepackage://ur_description/meshes/ur5e/visual/shoulder.dae / /geometry /visual collision geometry mesh filenamepackage://ur_description/meshes/ur5e/collision/shoulder.stl / /geometry /collision /link joint nameshoulder_pan_joint typerevolute parent linkbase_link / child linkshoulder_link / origin xyz0 0 0.1625 rpy0 0 0 / axis xyz0 0 1 / limit lower-3.1415926535 upper3.1415926535 effort330.0 velocity3.15 / dynamics damping0.5 friction0.1 / /joint这里的关键细节远超表面inertial中的originxyz 值是质心相对于shoulder_link坐标系原点的偏移。若设为(0,0,0)意味着质心与几何中心重合但实际 UR5e 肩部电机安装在壳体一侧质心必然偏移。我用 SolidWorks 测量过 UR5e 的shoulder_linkSTL 模型质心实际在(0.012, -0.018, 0.153)误差超过 3mm 就会导致重力矩计算偏差 15%collision使用 STL 而非 DAEDAE 是带纹理的渲染模型面片数高达 5 万Gazebo 碰撞检测会卡死STL 是简化后的三角网格面片数控制在 2000 以内且需用 MeshLab 的Quadric Edge Collapse Decimation功能降噪否则自碰撞检测会误报joint的damping和friction这两个参数直接决定关节伺服响应。damping0.5对应粘性阻尼系数值越大越“沉稳”但过大会导致响应迟钝friction0.1是库伦摩擦阈值低于此值电机无法驱动关节转动UR5e 官方手册给出的肩部静摩擦力矩为 12.5 N·m换算为friction值约为0.08~0.12。提示URDF 中gazebo标签是 Gazebo 专属扩展必须放在/joint或/link之后。例如为shoulder_pan_joint添加物理属性gazebo referenceshoulder_pan_joint implicitSpringDampertrue/implicitSpringDamper provideFeedbacktrue/provideFeedback /gazeboimplicitSpringDamper启用隐式弹簧阻尼模型比显式dynamics更稳定provideFeedback确保 Gazebo 向 ROS 发布该关节的实际力矩反馈这对力控抓取至关重要。3.2 SRDF 文件MoveIt 的“行为宪章”定义规划器能做什么、不能做什么SRDFSemantic Robot Description Format是 MoveIt 的语义层它不描述物理而描述“意图”。一个 Panda 机械臂的 SRDF 片段如下robot namepanda group namepanda_arm chain base_linkpanda_link0 tip_linkpanda_link8 / /group group namehand link namepanda_leftfinger / link namepanda_rightfinger / /group group namepanda_arm_hand group namepanda_arm / group namehand / /group end_effector namehand parent_linkpanda_link8 grouphand parent_grouppanda_arm / disable_collisions link1panda_link0 link2panda_link1 reasonAdjacent / disable_collisions link1panda_link1 link2panda_link2 reasonAdjacent / !-- ... 62 行 disable_collisions -- /robot这里的核心逻辑是group定义规划作用域panda_arm是 7 自由度臂hand是 2 指夹爪panda_arm_hand是两者的联合体。当你调用move_group.set_named_target(home)时MoveIt 会同时规划臂和手的关节目标end_effector绑定末端执行器parent_linkpanda_link8指定末端坐标系位置grouphand指定控制对象。若此处写错move_group.set_pose_target(pose)将无法解析末端位姿disable_collisions是性能关键Panda 有 9 个链接两两组合共 36 对可能碰撞但相邻链接如link0-link1在运动学上必然接触禁用它们的碰撞检测可将规划时间缩短 40%。UR5e 的disable_collisions列表长达 87 行全部来自 UR 官方ur5e_moveit_config包绝非随意填写。我曾因漏掉一行disable_collisions导致 MoveIt 在规划时对base_link和shoulder_link做冗余碰撞检测单次plan()耗时从 0.3 秒飙升至 2.7 秒。后来用rosrun moveit_commander moveit_commander_cmdline.py进入交互模式执行get_planning_scene()查看当前碰撞矩阵才定位到问题。3.3 Gazebo 与 MoveIt 的“握手协议”gazebo_ros_control插件如何桥接物理与规划MoveIt 规划出的是一系列关节角度序列trajectory_msgs/JointTrajectory而 Gazebo 需要的是力矩或位置指令。这个转换由gazebo_ros_control插件完成其配置藏在 URDF 的gazebo标签中gazebo plugin namegazebo_ros_control filenamelibgazebo_ros_control.so robotNamespace/my_robot/robotNamespace /plugin /gazebo但仅有插件还不够必须在 URDF 中为每个关节声明transmissiontransmission nameshoulder_pan_trans typetransmission_interface/SimpleTransmission/type joint nameshoulder_pan_joint hardwareInterfacePositionJointInterface/hardwareInterface /joint actuator nameshoulder_pan_motor mechanicalReduction1/mechanicalReduction /actuator /transmission这里的关键是hardwareInterface的选择PositionJointInterface接收目标位置radGazebo 内部用 PID 控制器跟踪适合大多数演示场景EffortJointInterface接收目标力矩N·m需自行实现力控算法但能真实模拟电机饱和、负载变化VelocityJointInterface接收目标角速度rad/s响应最快但位置精度差多用于轮式底盘。UR5e 官方推荐PositionJointInterface因其内置 PID 参数已针对实际电机调优。我在ur5e_gazebo_control.yaml中找到其配置shoulder_pan_joint: pid: {p: 100.0, i: 0.01, d: 10.0} shoulder_lift_joint: pid: {p: 80.0, i: 0.005, d: 8.0} # ... 其他关节这些参数不是随便写的。p100.0意味着位置误差 0.01 rad 时输出力矩增量为 1.0 N·md10.0抑制高频抖动。若你用ros2 control list_controllers查看会发现joint_state_controller发布/joint_states和joint_trajectory_controller接收/joint_trajectory是两个独立控制器后者正是gazebo_ros_control加载的。4. 实操过程从零搭建 UR5e 仿真平台的完整步骤与参数推导4.1 环境准备Ubuntu 22.04 ROS 2 Humble 的最小化安装策略网络热词中频繁出现“鱼香ROS一键安装”、“小鱼一键安装ROS”这类脚本本质是apt install ros-humble-desktop的封装但存在隐患它会安装ros-humble-gazebo-ros-pkgs、ros-humble-moveit等全部依赖总包体积超 2.3GB且部分包如ros-humble-ros1-bridge与单臂仿真无关。我推荐按需安装既节省磁盘又避免版本冲突# 1. 添加 ROS 2 Humble 源官方推荐 sudo apt update sudo apt install curl gnupg2 lsb-release curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - echo deb [arch$(dpkg --print-architecture)] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main | sudo tee /etc/apt/sources.list.d/ros2-latest.list # 2. 安装最小核心仅含 Gazebo 和 MoveIt 运行时 sudo apt update sudo apt install ros-humble-gazebo-ros-pkgs \ ros-humble-gazebo-ros-control \ ros-humble-moveit \ ros-humble-moveit-ros-planning-execution \ ros-humble-joint-state-publisher-gui \ ros-humble-xacro \ ros-humble-ros2-control \ ros-humble-ros2-controllers \ ros-humble-control-toolbox # 3. 验证安装关键检查项 ros2 pkg list | grep -E (gazebo|moveit|control) | wc -l # 应输出 ≥15 gazebo --version # 应为 11.12 ros2 control list_controllers # 应显示空列表尚未加载控制器注意不要安装ros-humble-desktop或ros-humble-perception。前者包含大量 GUI 工具如rqt在服务器环境会因缺少 X11 报错后者引入cv_bridge等依赖与机械臂仿真无关。我曾见学生因安装desktop导致gazebo_ros_control插件加载失败最终发现是libgazebo_ros_api_plugin.so与rqt的 Qt 版本冲突。4.2 获取并验证 UR5e 模型从官方源到本地适配的三步校验UR 官方 GitHub 仓库UniversalRobots/Universal_Robots_ROS2_Driver提供了ur_description包但直接使用存在风险。必须进行三步校验第一步检查 URDF 物理参数真实性下载ur_description/urdf/ur5e.urdf.xacro用xacro命令展开并检查关键参数# 展开 xacro 为 urdf ros2 run xacro xacro ur5e.urdf.xacro ur5e_check.urdf # 提取 shoulder_link 的 inertial 参数 grep -A 5 link name\shoulder_link\ ur5e_check.urdf确认mass5.2、ixx0.025等值与 UR 官方《UR5e Technical Specifications》文档一致。若发现mass1.0说明你拿到的是教学简化版需替换为ur_description的main分支最新版。第二步验证 Gazebo 兼容性打开ur5e.urdf.xacro搜索gazebo标签。UR 官方包中应包含gazebo referenceshoulder_pan_joint implicitSpringDampertrue/implicitSpringDamper provideFeedbacktrue/provideFeedback /gazebo若缺失provideFeedbackGazebo 将不发布关节力矩导致力控算法失效。第三步测试模型加载创建最小 launch 文件test_ur5e.launch.pyfrom launch import LaunchDescription from launch_ros.actions import Node from launch.actions import ExecuteProcess def generate_launch_description(): return LaunchDescription([ # 启动 Gazebo 空世界 ExecuteProcess(cmd[gazebo, --verbose, -s, libgazebo_ros_init.so, -s, libgazebo_ros_factory.so], outputscreen), # 加载 UR5e 模型 Node(packagegazebo_ros, executablespawn_entity.py, arguments[-entity, ur5e, -file, /path/to/ur5e_check.urdf, -x, 0, -y, 0, -z, 0], outputscreen) ])运行ros2 launch test_ur5e.launch.py观察 Gazebo 窗口若机械臂“瘫软”在地面检查inertial的mass是否过小若关节高速抖动检查joint的damping是否为 0若模型半透明闪烁是材质 shader 问题添加gazebo标签gazebo referenceshoulder_link materialGazebo/FlatBlack/material /gazebo4.3 MoveIt 配置包生成moveit_configs_utils的正确用法与避坑指南ROS 2 Humble 中moveit_setup_assistantMSA已被弃用官方推荐moveit_configs_utils。但直接运行ros2 run moveit_configs_utils setup_assistant会报错因为缺少依赖。正确流程是# 1. 创建工作空间 mkdir -p ~/ur5e_ws/src cd ~/ur5e_ws/src # 2. 复制 ur_description 到 src 下 git clone https://github.com/UniversalRobots/Universal_Robots_ROS2_Driver.git -b humble # 注意humble 分支对应 ROS 2 Humble # 3. 创建 moveit_config 包 ros2 run moveit_configs_utils moveit_configs_utils --help # 查看帮助 ros2 run moveit_configs_utils moveit_configs_utils \ --urdf-file /path/to/ur5e.urdf.xacro \ --srdf-file /path/to/ur5e.srdf \ --output-dir /path/to/ur5e_moveit_config \ --package-name ur5e_moveit_config但此命令会失败因为ur5e.urdf.xacro包含xacro:include需先展开# 正确做法用 xacro 展开后再生成 ros2 run xacro xacro /path/to/ur5e.urdf.xacro /tmp/ur5e.urdf ros2 run moveit_configs_utils moveit_configs_utils \ --urdf-file /tmp/ur5e.urdf \ --srdf-file /path/to/ur5e.srdf \ --output-dir /path/to/ur5e_moveit_config \ --package-name ur5e_moveit_config生成的ur5e_moveit_config包中最关键的文件是config/joint_limits.yaml# 关节运动范围rad shoulder_pan_joint: has_velocity_limits: true max_velocity: 3.15 has_acceleration_limits: true max_acceleration: 10.0 # 此值需根据 UR5e 手册设置UR5e 手册明确写出肩部关节最大加速度为10.0 rad/s²若设为100.0规划器会生成超出电机能力的轨迹Gazebo 中表现为关节“抽搐”。4.4 启动完整仿真Gazebo MoveIt Rviz 的四节点协同调试最终的ur5e_simulation.launch.py必须协调四个核心节点from launch import LaunchDescription from launch_ros.actions import Node from launch.actions import ExecuteProcess, IncludeLaunchDescription from launch.launch_description_sources import PythonLaunchDescriptionSource from ament_index_python.packages import get_package_share_directory import os def generate_launch_description(): # 1. Gazebo 世界 gazebo IncludeLaunchDescription( PythonLaunchDescriptionSource([os.path.join( get_package_share_directory(gazebo_ros), launch, gazebo.launch.py)]), launch_arguments{world: /path/to/empty.world}.items() ) # 2. 加载 UR5e 模型含 gazebo_ros_control spawn_entity Node(packagegazebo_ros, executablespawn_entity.py, arguments[-entity, ur5e, -file, /tmp/ur5e.urdf, -x, 0, -y, 0, -z, 0], outputscreen) # 3. 启动 MoveIt 控制器 move_group Node(packagemoveit_ros_move_group, executablemove_group, outputscreen, parameters[os.path.join(get_package_share_directory(ur5e_moveit_config), config, move_group.yaml), os.path.join(get_package_share_directory(ur5e_moveit_config), config, joint_limits.yaml)]) # 4. Rviz 可视化 rviz_node Node(packagerviz2, executablerviz2, arguments[-d, os.path.join(get_package_share_directory(ur5e_moveit_config), config, moveit.rviz)], outputscreen) return LaunchDescription([gazebo, spawn_entity, move_group, rviz_node])启动后关键调试步骤检查/joint_states是否发布ros2 topic echo /joint_states应看到name和position字段持续更新验证控制器状态ros2 control list_controllers应显示joint_state_controlleractive和joint_trajectory_controllerinactive手动激活轨迹控制器ros2 control switch_controllers --start joint_trajectory_controller在 Rviz 中点击Plan Execute若按钮灰色检查move_group终端是否有Failed to initialize planning scene monitor错误通常是robot_description参数未正确加载。实操心得Gazebo 界面“一直在闪”的根本原因是 GPU 渲染与 ROS 消息循环冲突。解决方案是在~/.gazebo/gui.ini中添加[gui]段落设置render_engineogre启动 Gazebo 时添加-r参数gazebo -r empty.world禁用实时渲染或改用gzserver无 GUI 版本进行后台仿真Rviz 单独显示。5. 常见问题与排查技巧实录从界面闪烁到规划失败的 12 类故障速查5.1 Gazebo 相关故障GPU 占用高、模型抖动、加载失败问题现象根本原因排查命令解决方案Gazebo 界面持续闪烁鼠标悬停卡顿Ogre 渲染器与 NVIDIA 驱动版本不兼容或 OpenGL 上下文冲突nvidia-smi查看 GPU 占用glxinfo | grep OpenGL version编辑~/.gazebo/gui.ini添加[gui] render_engineogre或启动时加-r参数禁用 GUI机械臂模型加载后立即瘫软在地关节无支撑力inertial中mass值过小如1.0重力矩不足ros2 topic echo /joint_states查看effort值是否接近 0修正 URDF 中mass为真实值UR5e 肩部5.2肘部3.8检查dynamics damping是否为 0Gazebo 启动报错Could not find library libgazebo_ros_control.sogazebo_ros_control包未安装或LD_LIBRARY_PATH未包含其路径find /opt/ros/humble -name libgazebo_ros_control.sosudo apt install ros-humble-gazebo-ros-control确保source /opt/ros/humble/setup.bash模型加载后部分链接透明或纹理丢失gazebo标签中未指定材质或 DAE 文件路径错误grep -r mesh filename /path/to/ur_description/在link的gazebo标签中添加materialGazebo/FlatBlack/material确保filename是package://协议5.2 MoveIt 相关故障Plan 按钮灰色、无 IK 解、规划超时问题现象根本原因排查命令解决方案Rviz 中Plan按钮灰色无法点击move_group节点未收到robot_description参数或joint_state_controller未激活ros2 param list | grep robot_descriptionros2 control list_controllers在move_group启动参数中显式添加robot_description:/robot_description运行ros2 control switch_controllers --start joint_state_controller点击Plan后终端报No IK solution found for goal poseSRDF 中end_effector的parent_link与 URDF 中末端链接名不一致ros2 run xacro xacro ur5e.urdf.xacro | grep panda_link8|ur5e_link_6检查 SRDF 的end_effector parent_link...与 URDF 中最后一个link name...是否完全匹配包括下划线规划耗时 5 秒Rviz 显示Planning request received后长时间无响应joint_limits.yaml中max_acceleration过大或disable_collisions缺失导致碰撞检测过载ros2 param get /move_group planning.max_velocity_scaling_factor将max_acceleration设为手册值UR5e 为10.0补全disable_collisions列表参考官方ur5e_moveit_config规划成功但执行时机械臂剧烈抖动gazebo_ros_control的 PID 参数未调优或hardwareInterface类型不匹配ros2 control list_controllers查看控制器类型若使用PositionJointInterface确保ur5e_gazebo_control.yaml中 PID 的p值在80~120之间d值5~15抑制抖动5.3 系统级故障ROS 2 节点通信中断、Topic 无数据、Launch 启动失败问题现象根本原因排查命令解决方案ros2 topic list无任何输出ros2 node list显示空ROS 2 daemon 未启动或RMW_IMPLEMENTATION