gazebo和moveit联合机械臂运动规划仿真(包含realsense视觉点云)

2023-05-16

1、gazebo仿真环境搭建

最终的场景:
在这里插入图片描述

使用的机械臂:AR3工业六轴机械臂
系统环境: ubuntu18 + ros-melodic
注:机械臂description包在github上下载的, 自己又对gazebo环境做了相应的修改。
下面是用到的主要的urdf描述文件:

<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from ar3.urdf                       | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED but it was unfortunately        | -->
<!-- =================================================================================== -->
<robot name="ar3" xmlns:xacro="http://www.ros.org/wiki/xacro">

  <material name="SwivelWhite">    <color rgba="1.0 1.0 1.0 1"/></material>
  <material name="SwivelLightGray"><color rgba="0.8 0.8 0.8 1"/></material>
  <material name="SwivelMedGray">  <color rgba="0.6 0.6 0.6 1"/></material>
  <material name="SwivelDarkGray"> <color rgba="0.4 0.4 0.4 1"/></material>
  <material name="SwivelRed">      <color rgba="0.5 0.4 0.4 1"/></material>
  <material name="SwivelGreen">    <color rgba="0.4 0.5 0.4 1"/></material>
  <material name="SwivelBlue">     <color rgba="0.4 0.4 0.5 1"/></material>

  <xacro:property name = "pi" value = "3.1415927" />

  <xacro:include filename="$(find realsense_ros_gazebo)/xacro/tracker.xacro"/>
  <xacro:include filename="$(find realsense_ros_gazebo)/xacro/depthcam.xacro"/>
        
  <xacro:realsense_d435 sensor_name="d435" parent_link="base_link" rate="10">
    <origin rpy="${pi/2} ${pi/2} 0 " xyz="0 -0.35 0.7"/>
  </xacro:realsense_d435>


  <link name="world" />

  <link name="base_link">
    <inertial>
      <origin rpy="0 0 0" xyz="-4.6941E-06 0.054174 0.038824"/>
      <mass value="0.7102"/>
      <inertia ixx="0.0039943" ixy="3.697E-07" ixz="-5.7364E-08" iyy="0.0014946" iyz="-0.00036051" izz="0.0042554"/>
    </inertial>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/base_link.STL"/>
      </geometry>
      <material name="">
        <color rgba="1 1 0 1"/>
      </material>
    </visual>
    <collision>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/base_link.STL"/>
      </geometry>
    </collision>
  </link>

  <joint name="joint_world" type="fixed">
    <parent link="world"/>
    <child link="base_link"/>
    <origin xyz="0 0 0" rpy="0 0 0" />  
  </joint>

  <link name="link_1">
    <inertial>
      <origin rpy="0 0 0" xyz="-0.022706 0.04294 -0.12205"/>
      <mass value="0.88065"/>
      <inertia ixx="0.0034" ixy="0.00042296" ixz="-0.00089231" iyy="0.0041778" iyz="0.0010848" izz="0.0027077"/>
    </inertial>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_1.STL"/>
      </geometry>
      <material name="">
        <color rgba="1 1 0 1"/>
      </material>
    </visual>
    <collision>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_1.STL"/>
      </geometry>
    </collision>
  </link>

  <joint name="joint_1" type="revolute">
    <origin rpy="${pi} 0 0" xyz="0 0 0.003445"/>
    <parent link="base_link"/>
    <child link="link_1"/>
    <axis xyz="0 0 1"/>
    <limit lower="-2.96706" upper="2.96706" effort="100" velocity="100"/>
  </joint>

  <link name="link_2">
    <inertial>
      <origin rpy="0 0 0" xyz="0.064818 -0.11189 -0.038671"/>
      <mass value="0.57738"/>
      <inertia ixx="0.0047312" ixy="0.0022624" ixz="0.00032144" iyy="0.0020836" iyz="-0.00056569" izz="0.0056129"/>
    </inertial>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_2.STL"/>
      </geometry>
      <material name="">
        <color rgba="1 1 0 1"/>
      </material>
    </visual>
    <collision>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_2.STL"/>
      </geometry>
    </collision>
  </link>

  <joint name="joint_2" type="revolute">
    <origin rpy="1.5708 0.5236 -1.5708" xyz="0 0.064146 -0.16608"/>
    <parent link="link_1"/>
    <child link="link_2"/>
    <axis xyz="0 0 -1"/>
    <limit lower="${-39.6 / 180.0 * pi}" upper="${pi / 2.0}" effort="100" velocity="100"/>
  </joint>

  <link name="link_3">
    <inertial>
      <origin rpy="0 0 0" xyz="-0.00029765 -0.023661 -0.0019125"/>
      <mass value="0.1787"/>
      <inertia ixx="0.0001685" ixy="-2.7713E-05" ixz="5.6885E-06" iyy="0.00012865" iyz="2.9256E-05" izz="0.00020744"/>
    </inertial>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_3.STL"/>
      </geometry>
      <material name="">
        <color rgba="1 1 0 1"/>
      </material>
    </visual>
    <collision>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_3.STL"/>
      </geometry>
    </collision>
  </link>

  <joint name="joint_3" type="revolute">
    <origin rpy="0 0 -1.04720367321" xyz="0.1525 -0.26414 0"/>
    <parent link="link_2"/>
    <child link="link_3"/>
    <axis xyz="0 0 -1"/>
    <limit lower="0.0174533" upper="2.5080381" effort="100" velocity="100"/>
  </joint>

  <link name="link_4">
    <inertial>
      <origin rpy="0 0 0" xyz="-0.0016798 -0.00057319 -0.074404"/>
      <mass value="0.34936"/>
      <inertia ixx="0.0030532" ixy="-1.8615E-05" ixz="-7.0047E-05" iyy="0.0031033" iyz="-2.3301E-05" izz="0.00022264"/>
    </inertial>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_4.STL"/>
      </geometry>
      <material name="">
        <color rgba="1 1 0 1"/>
      </material>
    </visual>
    <collision>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_4.STL"/>
      </geometry>
    </collision>
  </link>  

  <joint name="joint_4" type="revolute">
    <origin rpy="1.5708 -1.2554 -1.5708" xyz="0 0 0.00675"/>
    <parent link="link_3"/>
    <child link="link_4"/>
    <axis xyz="0 0 -1"/>
    <limit lower="-2.8710666" upper="2.8710666" effort="100" velocity="100"/>
  </joint>

  <link name="link_5">
    <inertial>
      <origin rpy="0 0 0" xyz="0.0015066 -1.3102E-05 -0.012585"/>
      <mass value="0.11562"/>
      <inertia ixx="5.5035E-05" ixy="-1.019E-08" ixz="-2.6243E-06" iyy="8.2921E-05" iyz="1.4437E-08" izz="5.2518E-05"/>
    </inertial>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_5.STL"/>
      </geometry>
      <material name="">
        <color rgba="1 1 0 1"/>
      </material>
    </visual>
    <collision>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_5.STL"/>
      </geometry>
    </collision>
  </link>

  <joint name="joint_5" type="revolute">
    <origin rpy="${pi} 0 -2.8262" xyz="0 0 -0.22225"/>
    <parent link="link_4"/>
    <child link="link_5"/>
    <axis xyz="1 0 0"/>
    <limit lower="-1.81776042" upper="1.81776042" effort="100" velocity="100"/>
  </joint>

  <link name="link_6">
    <inertial>
      <origin rpy="0 0 0" xyz="2.9287E-10 -1.6472E-09 0.0091432"/>
      <mass value="0.013863"/>
      <inertia ixx="1.3596E-06" ixy="3.0585E-13" ixz="5.7102E-14" iyy="1.7157E-06" iyz="6.3369E-09" izz="2.4332E-06"/>
    </inertial>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_6.STL"/>
      </geometry>
      <material name="">
        <color rgba="1 1 0 1"/>
      </material>
    </visual>
    <collision>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://ar3_description/meshes/link_6.STL"/>
      </geometry>
    </collision>
  </link>

  <joint name="joint_6" type="revolute">
    <origin rpy="0 0 3.1416" xyz="-0.000294 0 0.02117"/>
    <parent link="link_5"/>
    <child link="link_6"/>
    <axis xyz="0 0 1"/>
    <limit lower="-2.5848326" upper="2.5848326" effort="100" velocity="100"/>
  </joint>

  <!-- add table -->
  <link name="table">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.5 0.3 0.01" />
      </geometry>
        <material name="SwivelLightGray" /> 
    </visual> 
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.7 0.5 0.01" />
      </geometry>
    </collision>      
    <inertial>
      <mass value="9"/>
      <inertia ixx="9.0" ixy="0.0" ixz="0.0" iyy="9.0" iyz="0.0" izz="9.0"/>
    </inertial> 
  </link>

  <joint name="world_table" type="fixed">
    <parent link="world"/>
    <child link="table"/>
    <origin xyz="0 -0.4 0.25" rpy="0 0 0" />  
  </joint>
    
  <gazebo reference="table">
       <material>Gazebo/LightGray</material>
  </gazebo>

  <!-- add box1 -->
  <link name="box1">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.05 0.05 0.08" />
      </geometry>
        <material name="SwivelRed" /> 
    </visual> 
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.05 0.05 0.08" />
      </geometry>
    </collision>      
    <inertial>
      <mass value="9"/>
      <inertia ixx="9.0" ixy="0.0" ixz="0.0" iyy="9.0" iyz="0.0" izz="9.0"/>
    </inertial> 
  </link>

  <joint name="table_box1" type="fixed">
    <parent link="table"/>
    <child link="box1"/>
    <origin xyz="0 0 0.04" rpy="0 0 0" />  
  </joint>
    
  <gazebo reference="box1">
       <material>Gazebo/Red</material>
  </gazebo>

  <!-- add box2 -->
  <link name="box2">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.04 0.04 0.04" />
      </geometry>
        <material name="SwivelGreen" /> 
    </visual> 
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.04 0.04 0.04" />
      </geometry>
    </collision>      
    <inertial>
      <mass value="9"/>
      <inertia ixx="9.0" ixy="0.0" ixz="0.0" iyy="9.0" iyz="0.0" izz="9.0"/>
    </inertial> 
  </link>

  <joint name="table_box2" type="fixed">
    <parent link="table"/>
    <child link="box2"/>
    <origin xyz="0.1 0.05 0.025" rpy="0 0 0" />  
  </joint>
    
  <gazebo reference="box2">
       <material>Gazebo/Green</material>
  </gazebo>

  <!-- add cylinder1 -->
  <link name="cylinder1">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<cylinder length="0.02" radius="0.03"/>
      </geometry>
        <material name="SwivelGreen" /> 
    </visual> 
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<cylinder length="0.02" radius="0.03"/>
      </geometry>
    </collision>      
    <inertial>
      <mass value="9"/>
      <inertia ixx="9.0" ixy="0.0" ixz="0.0" iyy="9.0" iyz="0.0" izz="9.0"/>
    </inertial> 
  </link>

  <joint name="table_cylinder1" type="fixed">
    <parent link="table"/>
    <child link="cylinder1"/>
    <origin xyz="-0.1 0.05 0.015" rpy="0 0 0" />  
  </joint>
    
  <gazebo reference="cylinder1">
       <material>Gazebo/Blue</material>
  </gazebo>

  <!-- add box3 -->
  <link name="box3">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.02 0.02 0.02" />
      </geometry>
        <material name="SwivelRed" /> 
    </visual> 
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.02 0.02 0.02" />
      </geometry>
    </collision>      
    <inertial>
      <mass value="9"/>
      <inertia ixx="9.0" ixy="0.0" ixz="0.0" iyy="9.0" iyz="0.0" izz="9.0"/>
    </inertial> 
  </link>

  <joint name="world_box3" type="fixed">
    <parent link="world"/>
    <child link="box3"/>
    <origin xyz="0 -0.22 0.65" rpy="0 0 0" />  
  </joint>
    
  <gazebo reference="box3">
       <material>Gazebo/Red</material>
  </gazebo>


  <transmission name="transmission_1">
    <type>transmission_interface/SimpleTransmission</type>
    <joint name="joint_1">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
    </joint>
    <actuator name="motor_1">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>

  <transmission name="transmission_2">
      <type>transmission_interface/SimpleTransmission</type>
      <joint name="joint_2">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
      </joint>
      <actuator name="motor_2">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
          <mechanicalReduction>1</mechanicalReduction>
      </actuator>
  </transmission>

  <transmission name="transmission_3">
      <type>transmission_interface/SimpleTransmission</type>
      <joint name="joint_3">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
      </joint>
      <actuator name="motor_3">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
          <mechanicalReduction>1</mechanicalReduction>
      </actuator>
  </transmission>

  <transmission name="transmission_4">
      <type>transmission_interface/SimpleTransmission</type>
      <joint name="joint_4">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
      </joint>
      <actuator name="motor_4">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
          <mechanicalReduction>1</mechanicalReduction>
      </actuator>
  </transmission>

  <transmission name="transmission_5">
      <type>transmission_interface/SimpleTransmission</type>
      <joint name="joint_5">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
      </joint>
      <actuator name="motor_5">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
          <mechanicalReduction>1</mechanicalReduction>
      </actuator>
  </transmission>

  <transmission name="transmission_6">
      <type>transmission_interface/SimpleTransmission</type>
      <joint name="joint_6">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
      </joint>
      <actuator name="motor_6">
          <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
          <mechanicalReduction>1</mechanicalReduction>
      </actuator>
  </transmission>  

  <gazebo>
    <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
    <controlPeriod>0.05</controlPeriod>
    <legacyModeNS>true</legacyModeNS>
    </plugin>
  </gazebo>
  <gazebo reference="base_link">
      <selfCollide>true</selfCollide>
  </gazebo>
  <gazebo reference="link_1">
      <selfCollide>true</selfCollide>
  </gazebo>
  <gazebo reference="link_2">
      <selfCollide>true</selfCollide>
  </gazebo>
  <gazebo reference="link_3">
      <selfCollide>true</selfCollide>
  </gazebo>
  <gazebo reference="link_4">
      <selfCollide>true</selfCollide>
  </gazebo>
  <gazebo reference="link_5">
      <selfCollide>true</selfCollide>
  </gazebo>
  <gazebo reference="link_6">
      <selfCollide>true</selfCollide>
  </gazebo>

<!--camera-->
    <!-- <link name="camera_link">
        <visual>
            <origin xyz=" 0 0 0 " rpy="${pi/2} 0 ${pi/2}" />
            <geometry>
                <mesh filename="package://ar3_description/meshes/realsense_d435.stl"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 0.95"/>
            </material>
        </visual>
    </link>
 
    <joint name="camera_joint" type="fixed">
        <origin xyz="0 -0.35 0.7" rpy="${pi/2} ${pi/2} 0"/>
        <parent link="base_link"/>
        <child link="camera_link"/>
    </joint> -->
 
<!--gazebo-->
    <!-- <gazebo reference="camera_link"> 
            <sensor type="depth" name="camera">
            <update_rate>30.0</update_rate> 
            <camera name="head">
                <horizontal_fov>1.3962634</horizontal_fov> 
                <image>
                    <width>640</width> 
                    <height>480</height>
                    <format>R8G8B8</format> 
                </image>
                <clip>
                    <near>0.02</near> 
                    <far>300</far> 
                </clip>
            </camera>
            
            <plugin name="kinect_camera_controller" filename="libgazebo_ros_openni_kinect.so">
                <alwaysOn>true</alwaysOn>
                <updateRate>10</updateRate>
                <cameraName>camera</cameraName> 
                <imageTopicName>rgb/image_raw</imageTopicName>   
                
                <depthImageTopicName>depth/image_raw</depthImageTopicName>
		            <pointCloudTopicName>depth/points</pointCloudTopicName>
                <cameraInfoTopicName>rgb/camera_info</cameraInfoTopicName>
	            	<depthImageCameraInfoTopicName>depth/camera_info</depthImageCameraInfoTopicName>
                <frameName>camera_depth_optical_frame</frameName>
                <baseline>0.1</baseline>
                <distortion_k1>0.0</distortion_k1>
                <distortion_k2>0.0</distortion_k2>
                <distortion_k3>0.0</distortion_k3>
                <distortion_t1>0.0</distortion_t1>
                <distortion_t2>0.0</distortion_t2>
                <pointCloudCutoff>0.4</pointCloudCutoff>
            </plugin>
        </sensor>
    </gazebo> -->

</robot>


1.1 URDF文件解释

<xacro:include filename="$(find realsense_ros_gazebo)/xacro/tracker.xacro"/>
  <xacro:include filename="$(find realsense_ros_gazebo)/xacro/depthcam.xacro"/>
        
  <xacro:realsense_d435 sensor_name="d435" parent_link="base_link" rate="10">
    <origin rpy="${pi/2} ${pi/2} 0 " xyz="0 -0.35 0.7"/>
  </xacro:realsense_d435>

这一部分是引用realsense相机的urdf文件,加入到机械臂描述文件中。realsense相机描述文件在github上也可以下载。

<origin rpy="${pi/2} ${pi/2} 0 " xyz="0 -0.35 0.7"/>

这条语句描述的是相机的link相对于base_link的坐标变换,即坐标是(0,-0.35,0.7),姿态是先绕着相机自身坐标系的y轴按右手定则转90度,然后绕着新的坐标系的x轴转90度。


  <!-- add table -->
  <link name="table">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.5 0.3 0.01" />
      </geometry>
        <material name="SwivelLightGray" /> 
    </visual> 
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry >
				<box size="0.7 0.5 0.01" />
      </geometry>
    </collision>      
    <inertial>
      <mass value="9"/>
      <inertia ixx="9.0" ixy="0.0" ixz="0.0" iyy="9.0" iyz="0.0" izz="9.0"/>
    </inertial> 
  </link>

  <joint name="world_table" type="fixed">
    <parent link="world"/>
    <child link="table"/>
    <origin xyz="0 -0.4 0.25" rpy="0 0 0" />  
  </joint>
    
  <gazebo reference="table">
       <material>Gazebo/LightGray</material>
  </gazebo>

这一段的作用是在环境里添加桌子,主要包含 link , joint, gazebo说明 三块,其中joint决定桌子的位置相对world的位置,我这里也可以写成base_link,因为我这里的world和base_link坐标系是完全重合的。可以调整桌子的高度和距离机械臂的距离,不能太近,太近会撞到机械臂。
box放在桌子上作为物体,还加了一个障碍物作为机械臂moveit规划的避障物体。

1.2 启动gazebo

执行 roslaunch ar3_gazebo ar3_gazebo_bringup.launch
启动gazebo仿真环境,出现下面场景:
在这里插入图片描述终端可能会报错:
在这里插入图片描述这个不影响使用,可以不用管。

2、moveit配置

moveit官方教程:
https://moveit.picknik.ai/galactic/doc/tutorials/quickstart_in_rviz/quickstart_in_rviz_tutorial.html
安装moveit,可以使用moveit的配置助手

roslaunch moveit_setup_assistant setup_assistant.launch

官方教程也有给出。配置完成后,生成机械臂的moveit包。这里主要说一下规划组的运动学解算器的设置,在kinematic.yaml文件中:

manipulator:
  # kinematics_solver: kdl_kinematics_plugin/KDLKinematicsPlugin
  kinematics_solver: trac_ik_kinematics_plugin/TRAC_IKKinematicsPlugin
  kinematics_solver_search_resolution: 0.005
  kinematics_solver_timeout: 0.005

原本的解算器是kinematics_solver: kdl_kinematics_plugin/KDLKinematicsPlugin
改成了: kinematics_solver: trac_ik_kinematics_plugin/TRAC_IKKinematicsPlugin
有人说如果出现规划失败的问题:ABORTED: No motion plan found. No execution attempted.
就可以尝试换一下这个运动学插件。
如果换完之后编译出现缺少什么trac_ik包,安装即可。


修改默认的路径搜索算法

另外一点是在ompl_planning.yaml文件中,最后是

manipulator:
  default_planner_config: RRTkConfigDefault
  planner_configs:
    - SBLkConfigDefault
    - ESTkConfigDefault
    - LBKPIECEkConfigDefault
    - BKPIECEkConfigDefault
    - KPIECEkConfigDefault
    - RRTkConfigDefault
    - RRTConnectkConfigDefault
    - RRTstarkConfigDefault
    - TRRTkConfigDefault
    - PRMkConfigDefault
    - PRMstarkConfigDefault
    - FMTkConfigDefault
    - BFMTkConfigDefault
    - PDSTkConfigDefault
    - STRIDEkConfigDefault
    - BiTRRTkConfigDefault
    - LBTRRTkConfigDefault
    - BiESTkConfigDefault
    - ProjESTkConfigDefault
    - LazyPRMkConfigDefault
    - LazyPRMstarkConfigDefault
    - SPARSkConfigDefault
    - SPARStwokConfigDefault
  projection_evaluator: joints(joint_1,joint_2)
  longest_valid_segment_fraction: 0.005

其中,default_planner_config: RRTkConfigDefault是我后来添加的,可以删去,这里是设置默认的路径搜索算法(我个人理解),可以设置成其他的,从下面列出的之中选择。

3、启动moveit仿真环境

执行 roslaunch ar3_moveit_config ar3_moveit_bringup_demo.launch
这里我改了一下原有的启动文件,应该也可以直接使用原来的启动文件,我修改之后的ar3_moveit_bringup_demo.launch如下:

<launch>
    <!-- <rosparam command="load" file="$(find ar3_moveit_config)/config/joint_names.yaml" /> -->

    <include file="$(find ar3_moveit_config)/launch/planning_context.launch">
        <arg name="load_robot_description" value="false"/>
    </include>

    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher">
        <!-- <param name="/use_gui" value="true"/> -->
        <rosparam param="/source_list">[/joint_states]</rosparam>
    </node>
    
    <!-- Run the main MoveIt executable without trajectory execution (we do not have controllers configured by default) -->
    <include file="$(find ar3_moveit_config)/launch/move_group.launch">
        <arg name="allow_trajectory_execution" value="true"/>
        
    </include>

    <include file="$(find ar3_moveit_config)/launch/moveit_rviz.launch">
        <arg name="config" value="true"/>
    </include>

    <!-- World to base transform -->
    <node pkg="tf" type="static_transform_publisher" name="world_broadcaster" args = "0 0 0 0 0 0 world base_link 10" />

</launch>

启动moveit,并会打开rviz
在这里插入图片描述左下角是realense的rgb图像,右侧是机械臂+相机+桌子和物体+上方障碍物。


下面说一下坐标系的转换关系,这个对之后的物体坐标变换十分重要。
首先看一下world的frame和 base_link的frame,realsense的link的frame和table的frame,总共4个坐标系。
在这里插入图片描述左上角是相机link的frame,左下角是桌面的frame,右下角有world和base_link的frame,两个坐标系完全重合了。坐标系的颜色 R G B对应x y z轴。


然后是深度点云坐标系和world坐标系的关系
在这里插入图片描述可以发现深度点云坐标系的z轴是向下的,这里注意,之后相机发布的点云坐标,都是相对于这个
d435_depth_optical_frame的,都在这个坐标系下。因此从点云坐标,转换到base_link坐标系下,需要的过程是:

点云坐标  乘以  d435_depth_optical_frame相对于base_link的变换矩阵

这一点非常重要!!

4、利用深度相机获取目标点,并使用moveit规划路径

这一步是自己编写程序,订阅深度相机发布的点云话题,并声明一个moveit规划对象,设置目标的位置和姿态之后,使用moveit规划出路径并执行,然后gazebo中的机械臂就开始动了。
还是参考了官方文档:官方教程
官方使用了rviz自带的一个小界面,需要不断点next,我做了修改,代码如下

#include <moveit/move_group_interface/move_group_interface.h>
#include <moveit/planning_scene_interface/planning_scene_interface.h>
#include <moveit_msgs/DisplayRobotState.h>
#include <moveit_msgs/DisplayTrajectory.h>
#include <moveit_msgs/AttachedCollisionObject.h>
#include <moveit_msgs/CollisionObject.h>
#include <moveit_visual_tools/moveit_visual_tools.h>
#include <sensor_msgs/PointCloud.h>
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/point_cloud_conversion.h>
#include <ros/ros.h>
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Geometry>

#define pi (3.1415926535897932346f)
using namespace std;

sensor_msgs::PointCloud out_pointcloud;
float x;
float y;
float z;
void pointCloud2ToZ(const sensor_msgs::PointCloud2 &msg)
{
	sensor_msgs::convertPointCloud2ToPointCloud(msg, out_pointcloud);
    // cout << "points_size = " << out_pointcloud.points.size() << endl;
  float z_min=10;
  for (int i=0; i<out_pointcloud.points.size(); i++) {
    if(out_pointcloud.points[i].y < 0.1){
          if(out_pointcloud.points[i].z < z_min){
          z_min = out_pointcloud.points[i].z;
      }
    }
  }
  float x_sum=0;
  float y_sum=0;
  float z_sum=0;
  int points_num = 20;
  int j = 0;
  for (int i=0; i<out_pointcloud.points.size(); i++){
    if(out_pointcloud.points[i].y < 0.1 and out_pointcloud.points[i].z < z_min + 0.01){
      if(j >= points_num){
        break;
      }
      x_sum = x_sum + out_pointcloud.points[i].x;
      y_sum = y_sum + out_pointcloud.points[i].y;
      z_sum = z_sum + out_pointcloud.points[i].z;
      j = j+1;
    }
  }
  x = x_sum / points_num;
  y = y_sum / points_num;
  z = z_min;
}
int main(int argc, char** argv)
{
  ros::init(argc, argv, "move2object");
  ros::NodeHandle node_handle;
  ros::AsyncSpinner spinner(1);
  spinner.start();
  ros::Subscriber sub = node_handle.subscribe("/d435/depth/color/points", 1, pointCloud2ToZ);
  // ros::Subscriber sub = node_handle.subscribe("/camera/depth/points", 1, pointCloud2ToZ);
  ros::Duration(1).sleep();
  ros::spinOnce();
  cout<<  "target in camera frame is  "<<"  x= " << x << "   y = " << y <<  "   z= " << z <<endl;

  Eigen::Isometry3d T=Eigen::Isometry3d::Identity();
  Eigen::AngleAxisd rotation_vector(-pi,Eigen::Vector3d(0,1,0));  //  ar3_gazebo.urdf.xacro

  //  ar3_gazebo_copy.xacro
  Eigen::AngleAxisd rotation_vector1;
  rotation_vector1 = Eigen::AngleAxisd(0, Eigen::Vector3d::UnitZ()) * 
                      Eigen::AngleAxisd(-pi, Eigen::Vector3d::UnitY()) * 
                      Eigen::AngleAxisd(0, Eigen::Vector3d::UnitX());  

  T.rotate(rotation_vector);
  T.pretranslate(Eigen::Vector3d(0, -0.35, 0.7));


  Eigen::Vector3d v(x,y,z);  
  Eigen::Vector3d v_transformed = T*v;

  Eigen::Vector3d ea(pi/2, 0, pi);
  Eigen::Quaterniond quaternion;
  quaternion = Eigen::AngleAxisd(ea[0], Eigen::Vector3d::UnitZ()) * Eigen::AngleAxisd(ea[1], Eigen::Vector3d::UnitY()) * Eigen::AngleAxisd(ea[2], Eigen::Vector3d::UnitX());
  
  cout <<"target_xyz in  world  frame is  " << "  x= " << v_transformed[0] << "   y = " <<   v_transformed[1]  <<  "   z= " <<   v_transformed[2] <<endl;
  static const std::string PLANNING_GROUP = "manipulator";
  // The :move_group_interface:`MoveGroupInterface` class can be easily
  // setup using just the name of the planning group you would like to control and plan for.
  moveit::planning_interface::MoveGroupInterface move_group(PLANNING_GROUP);
  // We will use the :planning_scene_interface:`PlanningSceneInterface`
  // class to add and remove collision objects in our "virtual world" scene
  moveit::planning_interface::PlanningSceneInterface planning_scene_interface;
  // Raw pointers are frequently used to refer to the planning group for improved performance.
  const robot_state::JointModelGroup* joint_model_group = move_group.getCurrentState()->getJointModelGroup(PLANNING_GROUP);
  // Getting Basic Information
  // We can print the name of the reference frame for this robot.
  ROS_INFO_NAMED("tutorial", "Planning frame: %s", move_group.getPlanningFrame().c_str());
  // We can also print the name of the end-effector link for this group.
  ROS_INFO_NAMED("tutorial", "End effector link: %s", move_group.getEndEffectorLink().c_str());
  geometry_msgs::Pose target_pose1;
  target_pose1.orientation.w = quaternion.w();
  target_pose1.orientation.x = quaternion.x();
  target_pose1.orientation.y = quaternion.y();
  target_pose1.orientation.z =  quaternion.z();
  target_pose1.position.x = v_transformed[0];
  target_pose1.position.y = v_transformed[1];
  target_pose1.position.z = v_transformed[2]+0.02;

  cout << "move to traget  pose1 is  " <<"  x= " << target_pose1.position.x<< "   y = " <<  target_pose1.position.y <<  "   z= " <<   target_pose1.position.z <<endl;
  move_group.setPoseTarget(target_pose1);

  // Now, we call the planner to compute the plan and visualize it.
  // Note that we are just planning, not asking move_group
  // to actually move the robot.
  moveit::planning_interface::MoveGroupInterface::Plan my_plan;

  bool success = (move_group.plan(my_plan) == moveit::planning_interface::MoveItErrorCode::SUCCESS);

  // ROS_INFO_NAMED("tutorial", "Visualizing plan 1 (pose goal) %s", success ? "" : "FAILED");
  // ROS_INFO_NAMED("tutorial", "Visualizing plan 1 as trajectory line");
  
  move_group.move();

  ros::shutdown();
  return 0;
}

这个代码做了如下事情:
1、订阅realsense发布的点云话题,获取点云坐标;
2、遍历所有点云,找到了桌面上处于最高位置的点;
3、找出了在最高位置的点附近的点,并求这些点的平均x坐标和y坐标,以此作为最终目标的x 和y,最终目标的z还是用的是最高位置点的z;
4、把目标的(x,y,z)坐标乘以 d435_depth_optical_frame相对于base_link的变换矩阵,得到目标在base_link下的坐标;
5、手动设置目标的姿态,姿态就让末端link_6朝下,直接通过rpy姿态角度转四元数;
6、把目标的姿态和位置复赋值给 geometry_msgs::Pose target_pose1;,这里我把z加了0。02m,如果不加,可能在后面的路径规划的时候,会报错,显示无法规划出一条可行路径,原因就是目标点与其他物体非常接近,或者就在其他物体内部,不管怎么规划,机械臂最终都会和其他物体发生碰撞,所以显示规划失败,解决方法是设置合理的目标点,避免根其他物体相碰撞;
7、使用moceit规划一条路径,并执行。


视频效果:

gazebo仿真动画

5.资源包链接

包含机械臂描述文件和moveit配置文件,以及机械臂运动仿真的一个demo

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gazebo和moveit联合机械臂运动规划仿真(包含realsense视觉点云) 的相关文章

随机推荐

  • 修改docker默认存储路径

    默认情况下 xff0c docker镜像的默认存储路径是 var lib docker xff0c 这相当于直接挂载系统目录下 xff0c 而一般在搭系统时 xff0c 这个区都不会太大 xff0c 所以如果长期使用docker开发应用 x
  • 制作自己的rgb-d数据集

    今天自己用机器人采了一波数据 尝试着用自己采集的RGB D数据来跑slam2的RGB D例程 下面来记录一下 该文章主要是参考这篇博客 xff1a https blog csdn net qq 16481211 article detail
  • ROS中的一些基本概念

    主节点 xff08 master xff09 xff1a 负责节点到节点的消息与通信 用roscore命令来运行主节点 节点只有在需要注册自己信息或向其他节点发送请求时才能访问主节点 节点 xff08 node xff09 xff1a 是指
  • ros实践(一):编写一个自己的功能包

    创建ROS功能包的命令如下 xff1a catkin create pkg 功能包名称 依赖功能包1 依赖功能包2 实践 cd catkin ws src catkin create pkg my first ros pkg std msg
  • 多传感器融合技术(一)

    传感器融合 xff0c 一般可以分为四种 xff1a Early fusion Fusing the raw data xff0c 一般称为前融合 xff08 或数据融合 xff09 xff0c 汇总所有传感器的数据 xff0c 得到一个s
  • 多传感器融合技术(序)

    一 xff0e 概述 多传感器融合 xff08 Multi sensor Fusion MSF xff09 是利用计算机技术 xff0c 将来自多传感器或多源的信息和数据以一定的准则进行自动分析和综合 xff0c 以完成所需的决策和估计而进
  • 如何使用手机端、ipad端来编写博客

    今天收到一位粉丝的提问 xff0c 为此我特意去试了一下 xff0c 相信大家都知道CSDN的移动APP是不能写博客的 xff0c 那么我就想到用网页去试试 xff0c 但是当我搜索CSDN网页进去以后 xff0c 如图 xff1a 解法是
  • 上位机串口数据检验方式(二)——奇偶校验

    奇偶校验这个概念在逻辑设计里面经常会用到 xff0c 但有的人对奇偶校验的理解很混乱 奇偶校验是对数据传输正确性的一种校验方法 在数据传输前附加一位奇校验位 xff0c 用来表示传输的数据中 34 1 34 的个数是奇数还是偶数 xff0c
  • coco2017 数据集获取

    span class token comment 下载命令 span span class token function wget span http images cocodataset org zips train2017 zip sp
  • c++/opencv利用相机位姿估计实现2D图像像素坐标到3D世界坐标的转换

    最近在做自动泊车项目中的车位线检测 xff0c 用到了将图像像素坐标转换为真实世界坐标的过程 xff0c 该过程可以通过世界坐标到图像像素坐标之间的关系进行求解 xff0c 在我的一篇博文中已经详细讲解了它们之间的数学关系 xff0c 不清
  • C语言回调函数的定义和写法

    C语言中的回调函数 xff08 Callback Function xff09 1 定义和使用场合 回调函数是指 使用者自己定义一个函数 xff0c 实现这个函数的程序内容 xff0c 然后把这个函数 xff08 入口地址 xff09 作为
  • MATLAB到底有多厉害

    前言 有人说 xff0c MATLAB除了不会生孩子 xff0c 什么都会 矩阵运算 数据可视化 GUI xff08 用户界面 xff09 设计 甚至是连接其他编程语言 xff0c MATLAB都能轻松实现 xff01 那么 xff0c M
  • 无人机的偏航角,滚动角,俯仰角解释

    1 偏航角 xff08 yaw xff09 简单的定义 xff1a 就是实际航向与计划航向之间的夹角 xff0c 如图所示 深刻的定义 xff1a 机轴 xff08 沿机头方向 xff09 水平投影与地轴的夹角 xff0c 如图所示 或者
  • STM32H743,基于LL库实现adc采样(ADC+DMA+TIM)

    买了一块正点原子的阿波罗H743开发板 xff0c 最近在调试ADC采样 xff0c 由于CubeMx生成的是HAL库格式的代码 xff0c HAL库使用时太占用资源了不喜欢 xff0c 个人比较喜欢LL库 xff0c 这个库和STD库有点
  • 芯片热阻的理解

    基本概念 xff1a Ta xff1a Temperature Ambient 环境温度 Tc xff1a Temperature Case外壳温度 Tj xff1a Temperature Junction节点温度 热阻Rja xff1a
  • HDC1080传感器使用

    HDC1080温湿度传感器的驱动链接 xff08 函数都封装好了 xff0c 稍微改改就能用了 xff09 xff1a https download csdn net download qq 27718231 12656947 没有积分的小
  • 日常所用的耳机接口定义

    耳机插座在我们日常生活中是比较常见的一种电子元件 xff0c 其耳机插座的类型规格也区分有四段式耳机插座 三段式耳机插座等 三段式和四段式耳机的引脚定义如下 xff1a 四段式耳机插座接线的方法 xff0c 其只是比一般三段式的耳机插座增加
  • SX1268 SX1262中文数据手册

    在使用SX1268的时候 xff0c 只有英文数据手册 xff0c 中文手册没有人翻译 xff0c 现提供SX1262的中文手册方便大家在开发SX1268程序时使用 xff0c 这两款芯片使用上几乎一样的 xff0c 只是SX1268支持中
  • 用IO口模拟串口(外部中断+定时器)--附程序附测试结果

    给大家分享一下我用IO口模拟串口的一种方法 xff0c 经测试使用这种方法发送能支持115200波特率 xff0c 接收9600波特率测试没问题 xff0c 接收波特率能否提高受制于用户应用场景是否能允许微妙级别的频繁中断了 xff0c 我
  • gazebo和moveit联合机械臂运动规划仿真(包含realsense视觉点云)

    1 gazebo仿真环境搭建 最终的场景 xff1a 使用的机械臂 xff1a AR3工业六轴机械臂 系统环境 xff1a ubuntu18 43 ros melodic 注 xff1a 机械臂description包在github上下载的