跳转到主要内容博客列表
KOLIKO / 20262026年06月16日 / 10 min read

Moveit \&\& gazebo

本文介绍如何将MoveIt与Gazebo集成,实现机械臂的仿真与控制。详细讲解了添加惯性参数、碰撞属性、关节传动装置和Gazebo控制器插件等配置步骤,解决了机械臂抖动、控制器话题不匹配等问题。通过创建控制器配置文件、调整命名空间映射及使用simple控制器,最终实现机械臂在Gazebo中的正常运动,并成功与MoveIt规划系统通信。

2026年06月16日10 min read
ROSMoveItGazebo机器人控制

Moveit && gazebo

moveit集合gazebo使用

  1. 添加惯性参数和碰撞属性

  2. 为joint添加传动装置

  3. 添加gazebo控制器插件

配置gazebo

先安装功能包

1sudo apt-get install ros-<distro>-moveit ros-<distro>-gazebo-ros-pkgs ros-<distro>-gazebo-ros-control ros-<distro>-ros-control ros-<distro>-ros-controllers

新建xacro文件

复制urdf并修改后缀为.xacro

将原来的robot标签替换为如下

1<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="your_robot">

试一下是否可以在rviz里面打开即可

添加Gazebo和ros_control相关配置

在URDF/xacro文件中添加以下内容:

1<!-- 添加Gazebo颜色 --> 2<material name="blue"> 3 <color rgba="0 0 0.8 1"/> 4</material> 5 6<!-- 添加Gazebo插件 --> 7<gazebo> 8 <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so"> 9 <!-- 话题的命名空间 --> 10 <robotNamespace>/robot_arm</robotNamespace> 11 <robotSimType>gazebo_ros_control/DefaultRobotHWSim</robotSimType> 12 <legacyModeNS>true</legacyModeNS> 13 </plugin> 14</gazebo> 15 16<!-- 为每个关节添加传动装置 --> 17<!-- Transmissions for ROS Control --> 18<xacro:macro name="transmission_block" params="joint_name"> 19 <transmission name="${joint_name}_trans"> 20 <type>transmission_interface/SimpleTransmission</type> 21 <joint name="${joint_name}"> 22 <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface> 23 </joint> 24 <actuator name="${joint_name}_motor"> 25 <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface> 26 <mechanicalReduction>1</mechanicalReduction> 27 </actuator> 28 </transmission> 29</xacro:macro> 30 31<!-- 为六轴机械臂创建传输块 --> 32<xacro:transmission_block joint_name="joint1"/> 33<xacro:transmission_block joint_name="joint2"/> 34<xacro:transmission_block joint_name="joint3"/> 35<xacro:transmission_block joint_name="joint4"/> 36<xacro:transmission_block joint_name="joint5"/> 37<xacro:transmission_block joint_name="joint6"/> 38<!-- 为其他6个关节重复上述配置 -->

在gazebo中加载模型

需要修改加深内容

1<launch> 2 3 <!-- these are the arguments you can pass this launch file, for example paused:=true --> 4 <arg name="paused" default="false"/> 5 <arg name="use_sim_time" default="true"/> 6 <arg name="gui" default="true"/> 7 <arg name="headless" default="false"/> 8 <arg name="debug" default="false"/> 9 10 <!-- 启动gazebo仿真环境 --> 11 <include file="$(find gazebo_ros)/launch/empty_world.launch"> 12 <arg name="debug" value="$(arg debug)" /> 13 <arg name="gui" value="$(arg gui)" /> 14 <arg name="paused" value="$(arg paused)"/> 15 <arg name="use_sim_time" value="$(arg use_sim_time)"/> 16 <arg name="headless" value="$(arg headless)"/> 17 </include> 18 19 <!-- Load the URDF into the ROS Parameter Server --> 20 <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find probot_description)/urdf/probot_anno.xacro'" /> 21 22 23 <!-- 在gazebo中加载模型--> 24 <!--Run a python script to the send a service call to gazebo_ros to spawn a URDF robot --> 25 <node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen" 26 args="-urdf -model probot_anno -param robot_description"/> 27 28 29</launch>

创建控制器配置文件

your_arm_gazebo/config/目录下创建arm_control.yaml:

1arm_controller: 2 type: position_controllers/JointTrajectoryController 3 joints: 4 - joint1 5 - joint2 6 - joint3 7 - joint4 8 - joint5 9 - joint6 10 - joint7 11 constraints: 12 goal_time: 0.6 13 stopped_velocity_tolerance: 0.05 14 joint1: {trajectory: 0.1, goal: 0.1} 15 joint2: {trajectory: 0.1, goal: 0.1} 16 joint3: {trajectory: 0.1, goal: 0.1} 17 joint4: {trajectory: 0.1, goal: 0.1} 18 joint5: {trajectory: 0.1, goal: 0.1} 19 joint6: {trajectory: 0.1, goal: 0.1} 20 joint7: {trajectory: 0.1, goal: 0.1} 21 stop_trajectory_duration: 0.5 22 state_publish_rate: 50 23 action_monitor_rate: 10 24joint_state_controller: 25 type: joint_state_controller/JointStateController 26 publish_rate: 50

运行会出现报错

1[ERROR] [1744080720.643849736, 0.186000000]: No p gain specified for pid. Namespace: /robot_arm/gazebo_ros_control/pid_gains/joint1 2[ERROR] [1744080720.644095052, 0.186000000]: No p gain specified for pid. Namespace: /robot_arm/gazebo_ros_control/pid_gains/joint2 3[ERROR] [1744080720.644285327, 0.186000000]: No p gain specified for pid. Namespace: /robot_arm/gazebo_ros_control/pid_gains/joint3 4[ERROR] [1744080720.644453725, 0.186000000]: No p gain specified for pid. Namespace: /robot_arm/gazebo_ros_control/pid_gains/joint4 5[ERROR] [1744080720.644617775, 0.186000000]: No p gain specified for pid. Namespace: /robot_arm/gazebo_ros_control/pid_gains/joint5 6[ERROR] [1744080720.644784731, 0.186000000]: No p gain specified for pid. Namespace: /robot_arm/gazebo_ros_control/pid_gains/joint6

这里是因为参数话题不匹配导致

参数添加

1arm_controller: 2 type: position_controllers/JointTrajectoryController 3 joints: 4 - joint1 5 - joint2 6 - joint3 7 - joint4 8 - joint5 9 - joint6 10 - joint7 11 constraints: 12 goal_time: 0.6 13 stopped_velocity_tolerance: 0.05 14 joint1: {trajectory: 0.1, goal: 0.1} 15 joint2: {trajectory: 0.1, goal: 0.1} 16 joint3: {trajectory: 0.1, goal: 0.1} 17 joint4: {trajectory: 0.1, goal: 0.1} 18 joint5: {trajectory: 0.1, goal: 0.1} 19 joint6: {trajectory: 0.1, goal: 0.1} 20 joint7: {trajectory: 0.1, goal: 0.1} 21 22 gazebo_ros_control: 23 joint1: {p: 1000, i: 0, d: 10} 24 joint2: {p: 1000, i: 0, d: 10} 25 joint3: {p: 1000, i: 0, d: 10} 26 joint4: {p: 1000, i: 0, d: 10} 27 joint5: {p: 500, i: 0, d: 5} 28 joint6: {p: 500, i: 0, d: 5} 29 joint7: {p: 500, i: 0, d: 5} 30 31 stop_trajectory_duration: 0.5 32 state_publish_rate: 50 33 action_monitor_rate: 10 34joint_state_controller: 35 type: joint_state_controller/JointStateController 36 publish_rate: 500

在launch加入载入参数

1<rosparam file="$(find livelybot_description)/robot_param/7dof_control.yaml" command="load" />

如果机器人姿态不对可以修改一下姿态

1<!-- 在URDF的<robot>标签内添加以下内容 --> 2<link name="world"/> <!-- 零质量的虚拟根链接 --> 3 4<joint name="world_to_base" type="fixed"> 5 <origin xyz="0 0 1" rpy="0 -1.57 0"/> 6 <parent link="world"/> 7 <child link="base_link"/> 8</joint>

在机械臂载入时,会有机械臂抖动的情况

这里采用加入阻尼参数使用。

1<!-- 关键阻尼参数 --> 2<dynamics damping="1.0" friction="1.0"/> <!-- 阻尼单位:Nm/(rad/s) -->

于是就可以在gazebo正常打开了

Image

配置Moveit

可以参考链接

https://dcnran67llv5\.feishu\.cn/wiki/Hcl8wgtF2ihtzOk78Lecm80Onoe

1roslaunch moveit_setup_assistant setup_assistant.launch
  1. 选择"Create New MoveIt Configuration Package"

  2. 加载你的URDF/xacro文件

  3. 配置自碰撞矩阵

  4. 定义虚拟关节(如果需要)

  5. 定义规划组(通常为arm组和可能的手爪组)

  6. 定义机器人姿态(如"home"姿势)

  7. 配置末端执行器

  8. 配置被动关节(如果有)

  9. 生成配置文件并保存到your_arm_moveit_config

配置gazebo moveit文件

  1. arm_gazebo_world.launch

用来加载gazebo中的机械臂模型和世界

1<launch> 2 3 <!-- these are the arguments you can pass this launch file, for example paused:=true --> 4 <arg name="paused" default="false"/> 5 <arg name="use_sim_time" default="true"/> 6 <arg name="gui" default="true"/> 7 <arg name="headless" default="false"/> 8 <arg name="debug" default="false"/> 9 10 <!-- We resume the logic in empty_world.launch --> 11 <include file="$(find gazebo_ros)/launch/empty_world.launch"> 12 <arg name="debug" value="$(arg debug)" /> 13 <arg name="gui" value="$(arg gui)" /> 14 <arg name="paused" value="$(arg paused)"/> 15 <arg name="use_sim_time" value="$(arg use_sim_time)"/> 16 <arg name="headless" value="$(arg headless)"/> 17 </include> 18 19 <!-- Load the URDF into the ROS Parameter Server --> 20 <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find urdf_7dof)/urdf/urdf_7dof.xacro'" /> 21 22 <!-- Run a python script to the send a service call to gazebo_ros to spawn a URDF robot --> 23 <node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen" 24 args="-urdf -model arm_7dof -param robot_description"/> 25 26</launch> 27
  1. arm_gazebo_states.launch

用来加载gazebo中的控制器,发布tf

1<launch> 2 <!-- 将关节控制器的配置参数加载到参数服务器中 --> 3 <rosparam file="$(find livelybot_gazebo)/config/arm7dof_gazebo_joint_states.yaml" command="load"/> 4 5 <node name="joint_controller_spawner" pkg="controller_manager" type="spawner" respawn="false" 6 output="screen" ns="/arm_7dof" args="joint_state_controller" /> 7 8 <!-- 运行robot_state_publisher节点,发布tf --> 9 <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" 10 respawn="false" output="screen"> 11 <remap from="/joint_states" to="/arm_7dof/joint_states" /> 12 </node> 13 14</launch>
  1. arm_trajectory_controller.launch

这里加载JointTrajectoryController,以及pid参数

1<launch> 2 3 <rosparam file="$(find livelybot_gazebo)/config/arm7dof_trajectory_control.yaml" command="load"/> 4 5 <node name="arm_controller_spawner" pkg="controller_manager" type="spawner" respawn="false" 6 output="screen" ns="/arm_7dof" args="arm_controller"/> 7 8</launch> 9
  1. moveit_planning_execution.launch

打开rviz建立通信

1<launch> 2 # The planning and execution components of MoveIt! configured to 3 # publish the current configuration of the robot (simulated or real) 4 # and the current state of the world as seen by the planner 5 <include file="$(find moveit_7dof)/launch/move_group.launch"> 6 <arg name="publish_monitored_planning_scene" value="true" /> 7 </include> 8 9 # The visualization component of MoveIt! 10 <include file="$(find moveit_7dof)/launch/moveit_rviz.launch"> 11 <arg name="rviz_config" value="$(dirname)/moveit.rviz"/> 12 </include> 13 14 <!-- We do not have a robot connected, so publish fake joint states --> 15 <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher"> 16 <param name="/use_gui" value="false"/> 17 <rosparam param="/source_list">[/arm_7dof/joint_states]</rosparam> 18 </node> 19 20</launch> 21

简化模型

重建模型并做好配合在导出,取stl文件使用

[meshes-J.zip]

[meshes.zip]

Image

简化前

Image

简化后(把电机取消)

效果

Image

Image

[2025年04月15日 屏幕视频 09时33分06秒.webm]

话题关系

Image

demo_gazebo.launch文件研究

在moveit生成的文件里面包括了gazebo和moveit的联动,但是在运行的时候会有问题,这里解读一下这个文件

不同点

这里和上面的文件一一对比,寻找不同的地方:

move_group的参数不同

在moveit的demo.launch启动moveit的时候没有传入这个参数

<arg name="publish_monitored_planning_scene" value="true" />

没有joint_state_publisher

1<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher"> 2 <param name="/use_gui" value="false"/> 3 <rosparam param="/source_list">[/arm_7dof/joint_states]</rosparam> 4 </node>

应该是因为默认发送到joint_states,但是我的机械臂有命名空间/arm_7dof,所以这里需要做一层转发

缺少joint_states的重映射

在gazebo里面估计也是默认发送到/joint_states,这里需要remap,发布robot机器人的关节状态

1<!-- 运行robot_state_publisher节点,发布tf --> 2<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" 3 respawn="false" output="screen"> 4 <remap from="/joint_states" to="/arm_7dof/joint_states" /> 5</node>

将上面的控制器还有命名空间映射全都调整好之后运行,发现拖动execute的时候仍然有问题。

发现报错

1[ WARN] [1744788882.991439781, 10.831000000]: Failed to read controllers from /controller_manager/list_controllers 2[ERROR] [1744788882.991552241, 10.831000000]: Unable to identify any set of controllers that can actuate the specified joints: [ joint1 joint2 joint3 joint4 joint5 joint6 joint7 ] 3[ERROR] [1744788882.991606397, 10.831000000]: Known controllers and their joints:

这里可以看到找不到/controller_manager/list_controllers这个东西。

在普通运行的时候,我们使用的是simple_moveit_controller.yaml里面的配置。

可以看到move_group里面有这样一个代码

1<!-- Trajectory Execution Functionality --> 2 <include ns="move_group" file="$(dirname)/trajectory_execution.launch.xml" if="$(arg allow_trajectory_execution)"> 3 <arg name="moveit_manage_controllers" value="true" /> 4 <arg name="moveit_controller_manager" value="$(arg moveit_controller_manager)" /> 5 <arg name="fake_execution_type" value="$(arg fake_execution_type)" /> 6 </include>

传入的参数为

1<arg name="moveit_controller_manager" value="$(arg moveit_controller_manager)" />

在trajectory_execution.launch.xml这样使用

1<include file="$(dirname)/$(arg moveit_controller_manager)_moveit_controller_manager.launch.xml" pass_all_args="true" />

而在move_group里面默认参数为

1<arg name="moveit_controller_manager" default="simple" />

所以之前调用的都是simple_moveit_controller_manager.launch.xml文件。

但是在demo_gazebo.launch启动demo.launch的时候调用的参数是这个

1<arg name="moveit_controller_manager" value="ros_control" />

所以我们需要新建一个ros_control_moveit_controller_manager.launch.xml,这样一个文件, 他的内容改称simple_moveit_controller_manager.launch.xml一样就好了

至于内容是否修改可自定义

1<launch> 2 <!-- Define the MoveIt controller manager plugin to use for trajectory execution --> 3 <param name="moveit_controller_manager" value="moveit_simple_controller_manager/MoveItSimpleControllerManager" /> 4 5 <!-- Load controller list to the parameter server --> 6 <rosparam file="$(find moveit_7dof)/config/simple_moveit_controllers.yaml" /> 7 <rosparam file="$(find moveit_7dof)/config/ros_controllers.yaml" /> 8</launch>

都修改了之后发现还是不行,

最后通过调试发现

1<param name="moveit_controller_manager" value="moveit_simple_controller_manager/MoveItSimpleControllerManager" />

发现是需要simple的controller才可以,不然的话就会提示找不到controllist