在ubuntu20.04(ROS noetic版)上做moveit的gazebo仿真(包含视觉相机)

前言:

        最近,博主一直在做手眼标定的一些机械臂方向的工作,不过标定的结果误差较大,于是我就怀疑相机和机械臂方向的问题,再加上现场的机械臂使用起来不是太方便,于是我就想起了之前的gazebo仿真环境,其实之前我就在gazebo下实现过moveit的路径规划和八叉树环境感知和机械臂避障的,不过当我按照我之前的心路去实现时发现这条路在新版的moveit上不行,于是经过几个日夜便有了此文章。

        其实,网络上的教程很多的,不过绝大数都是针对melodic版本或者ros2来说的,包括我之前也是该古月居教程https://mp.weixin.qq.com/s?__biz=MzU1NjEwMTY0Mw==&mid=2247485853&idx=1&sn=d179fba0d0b700b7325e108cee2c138b&chksm=fbcb70f9ccbcf9ef6ccba6b41c5ec0225ae2ae8b0ae5ce31086e696e51a7806f7fd0b9c05440&scene=27和一些文章来学习并搭建的,但是这招对noetic好像不太适用,我搭建了几天都没有什么效果,所以我推荐用noetic版本的可以试试该方法。

正文:

一、准备urdf/xacro模型文件

        在正式开始前,这个文件包是必要的,需要我们自己去准备好,如果你自己没有机器人模型文件我可以推荐你下载我自己制作的kuka模型文件功能包,不过你也可以去下载ur5机械臂或者其他机械臂模型文件。

        如果,你想把自己的机械臂制作为模型包,那么你需要安装SolidWorks和相关插件,具体操作可以参考特别章节-0.1 SolidWorks导出机械臂的URDF模型各个关节坐标系设置-CSDN博客,如果需要技术支持可以联系我主页邮箱或者对应的QQ。

二、安装moveit

   1 、下载安装moveit

sudo apt-get install ros-noetic-moveit

        如果你不放心,可以将所有的moveit的插件和相关软件安装了。

sudo apt-get install ros-noetic-moveit*

2、验证moveit安装结果和版本号

moveit_version

        我这里是 1.1.14 当然哈 随着时间推移 估计你会是 1.1.15 或者其他最新版本 不过这不重要

三、启动moveit配置参数

1、开启moveit配置器

        进入你的工作空间并刷新环境

cd test_ws #你的工作空间目录
source devel/setup.bash

        启动配置器

roslaunch moveit_setup_assistant setup_assistant.launch
# 第一次输入该命令不能补全的话 就把功能包打完再补全

2、加载模型文件

点击创建新的配置包后点击Browse,选择你的urdf或者xarco文件,选择好后点击右下角的Load Files。

如果报错如下:

那就是你没有刷新工作空间环境。

3、碰撞关节检测

        该环节主要是用于以后的路径规划时减少自我受限的碰撞计算。

         这里创建就用默认的95%都可以。

4、虚拟关节

        这个选项在你没有外部轴需求的情况下可以忽略,还有就是你没有与空间world坐标系固定关系的情况下可以利用这个来配置和world的关系,这里我就忽略不细说了。
 

5、规划组创建

        这个选项的目的是为了创建路径规划的控制对象,像我这个模型就只是一个机械臂,那么一个组就可以了,如果你有夹爪或则多个机械臂,那么就需要配置多个组。

 

        我的配置结果如下

6、姿态添加

        该选项的意图是在添加一个或则多个姿态并命名,在以后的调用中可以快速调取该姿态对应的关节数据。

7、不重要选项

        这里的末端工具配置、被动关节配置 以及3D传感器配置对于我们目前来说还不太重要,所以这里先不描述。

8、控制器配置(重要)

        这个选项的配置可谓是非常重要,博主也是在这里摔个狗吃屎。这也是区别于其他教程的地方,其他教程估计是自己配置一些参数文件,但是我这里发现其实moveit自己带的选项就可以傻瓜化配置,唉...还是觉得自己太聪明不够傻瓜...Ha Ha Ha。

控制器类型我选择的是 position_controllers/JointTrajectoryController

也可以试试其他控制器类型,看看可不可以用起来

9、重新得到模型描述文件

        通过这些配置后,moveit会帮我们重新生成一个urdf的描述文件,其中就包含了你控制器的仿真驱动,一般来说你可以通过这个文件来修改或者直接作为你的模型启动文件。

        如果你没有直接修改描述文件的按钮,我建议你可以将绿色部分复制并修改你的源文件,然后等配置结束了去修改launch文件,当然你也可以不这么做,因为moveit会在你配置结束后将修改后的文件另存在配置好的包的config下,一般为gazebo_机器人名.urdf文件,并且该文件会在配置好的包的launch下的gazebo.launch文件的16行被加载,如果你想修改为自己配置的描述文件,将该gazebo.launch文件的16行文件路径改为自己的描述文件就可以了。

10、作者信息

        该选项是用于填充包作者的信息的,moveit是要求必须要填写的,不然不能生成包的。

11、创建配置包

        这是配置参数的最后一步,就是生成包文件。

四、启动仿真

        在上面的配置中,我们完成了仿真控制参数包的生成,同时我们应当注意第三中的第8和9点。

这个时候,我们只需要将工作空间编译并刷新环境后就可以运行仿真示例啦。

# cd到工作空间目录下
# 编译空间
catkin_make

# 刷新环境
source devel/setup.bash 

# 运行demo
roslaunch kuka_moveit_config demo_gazebo.launch

        一般来说,你会缺少控制器从而导致运行失败,所以直接下载下面的控制器和joint等节点发布器。

sudo apt-get install ros-noetic-ros-controllers

sudo apt-get install ros-noetic-joint-state-controller

sudo apt-get install ros-noetic-effort-controllers

sudo apt-get install ros-noetic-position-controllers 

        出现这个情况,那么就是你对应的joint控制器没安装

        那么只需要

sudo apt-get install ros-noetic-joint-trajectory-controller

        安装完成,刷新环境再运行 

        这个错误影响不大,不必惊慌。

运行结果:

五、配置相机插件

        其实,我们在生成的 机器人_moveit_config包的launch下的gazebo.launch文件的第16行可以看到

        所以,接第9点的结尾那段我们只需要将 机器人_moveit_config包的config下生成的gazebo_机器人.urdf文件中 第9点所说的新增加的绿色部分的插件放到你的原始模型文件中,这就完成了电机驱动的安装,在把这里的这个模型文件改为你的模型描述文件的路径就可以了。

        如果是源模型文件是xacro文件,那么修改16行如同下面的格式        

<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find kuka_description)/urdf/xacro/kuka.xacro'" />

        其实到此,你就把一个仿真包和你的模型包建立了联系,那么我们只需要给我们模型的urdf或者xacro文件再装一个相机插件就可以了,我这里装的是kinect_camera相机,可以有点云和rgb图像。

        直接将下面的驱动描述复制到你的模型源文件中,就像电机驱动一样。

    <!-- 相机驱动 -->
    <!-- 相机挂载的tf树  -->
    <gazebo reference="rgb">
     <sensor type="depth" name="camera">
      <always_on>true</always_on>
      <update_rate>20</update_rate>
      <camera>
        <horizontal_fov>${60.0 * PI/ 180.0}</horizontal_fov>
        <image>
            <width>640</width>
            <height>480</height>
            <format>R8G8B8</format>
        </image>
        <clip>
            <near>0.05</near>
            <far>15.0</far>
        </clip>
      </camera>
      <plugin name="kinect_camera_controller" filename="libgazebo_ros_openni_kinect.so">
        <cameraName>camera</cameraName>
        <alwaysOn>true</alwaysOn>
        <updateRate>10</updateRate>
        <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>rgb</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>

最后,我的模型文件就是下面这样(参考对比,不用复制)

<?xml version="1.0"?>
<robot name="kuka" xmlns:xacro="http://www.ros.org/wiki/xacro">

    <xacro:property name="PI" value="3.1415926536"/>
    <xacro:property name="EFFORT" value="1000"/>
    <xacro:include filename="$(find kuka_description)/urdf/xacro/arm/arm.xacro" />
    <xacro:include filename="$(find kuka_description)/urdf/xacro/sensor/cam.xacro" />
  
  <!-- joint_cam -->
  <joint name="joint_cam" type="fixed">
    <origin xyz="-0.062591 0.031343 0.013" rpy="0.7107 -1.5708 -1.1751" />
    <parent link="link6" />
    <child  link="cam" />
  </joint>
  
  <!-- 虚拟相机坐标系 -->
  <link name="rgb"/>
  <joint name="rgb_joint" type="fixed">
    <origin xyz="0 0 0.1" rpy="0 -1.57 0"/>
    <parent link="cam"/>
    <child link="rgb"/>
  </joint>
  
  <!-- 电机驱动 -->
      <transmission name="trans_joint1">
        <type>transmission_interface/SimpleTransmission</type>
        <joint name="joint1">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        </joint>
        <actuator name="joint1_motor">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
            <mechanicalReduction>1</mechanicalReduction>
        </actuator>
    </transmission>
    <transmission name="trans_joint2">
        <type>transmission_interface/SimpleTransmission</type>
        <joint name="joint2">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        </joint>
        <actuator name="joint2_motor">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
            <mechanicalReduction>1</mechanicalReduction>
        </actuator>
    </transmission>
    <transmission name="trans_joint3">
        <type>transmission_interface/SimpleTransmission</type>
        <joint name="joint3">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        </joint>
        <actuator name="joint3_motor">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
            <mechanicalReduction>1</mechanicalReduction>
        </actuator>
    </transmission>
    <transmission name="trans_joint4">
        <type>transmission_interface/SimpleTransmission</type>
        <joint name="joint4">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        </joint>
        <actuator name="joint4_motor">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
            <mechanicalReduction>1</mechanicalReduction>
        </actuator>
    </transmission>
    <transmission name="trans_joint5">
        <type>transmission_interface/SimpleTransmission</type>
        <joint name="joint5">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        </joint>
        <actuator name="joint5_motor">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
            <mechanicalReduction>1</mechanicalReduction>
        </actuator>
    </transmission>
    <transmission name="trans_joint6">
        <type>transmission_interface/SimpleTransmission</type>
        <joint name="joint6">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        </joint>
        <actuator name="joint6_motor">
            <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
            <mechanicalReduction>1</mechanicalReduction>
        </actuator>
    </transmission>
    <gazebo>
        <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
            <robotNamespace>/</robotNamespace>
        </plugin>
    </gazebo>
    
    <!-- 相机驱动 -->
    <gazebo reference="rgb">
     <sensor type="depth" name="camera">
      <always_on>true</always_on>
      <update_rate>20</update_rate>
      <camera>
        <horizontal_fov>${60.0 * PI/ 180.0}</horizontal_fov>
        <image>
            <width>640</width>
            <height>480</height>
            <format>R8G8B8</format>
        </image>
        <clip>
            <near>0.05</near>
            <far>15.0</far>
        </clip>
      </camera>
      <plugin name="kinect_camera_controller" filename="libgazebo_ros_openni_kinect.so">
        <cameraName>camera</cameraName>
        <alwaysOn>true</alwaysOn>
        <updateRate>10</updateRate>
        <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>rgb</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>

         完成这些后再运行demo_gazebo.launch文件就会发现话题列表有图像话题产生,打开rviz也可以添加并可视化图像数据。

点云问题: 

        我们在后续的开发中有同学提出,这个相机采集的点云和实际位置不匹配,这个问题实际上是kinect_camera_controller相机插件中rgb坐标系和depth坐标系有旋转导致的,所以说我们需要再建一个虚拟坐标系和rgb虚拟坐标系产生旋转,最后把点云(depth)坐标系绑在他上面。

实际操作: 

        1、在上面的urdf文件中的虚拟坐标系下增加一个depth坐标系。

        <!-- 虚拟相机坐标系 -->
        <link name="rgb"/>
        <joint name="rgb_joint" type="fixed">
            <origin xyz="0 0 0.1" rpy="0 -1.57 0"/>
            <parent link="cam"/>
            <child link="rgb"/>
        </joint>
        
        <!-- 新增加的depth坐标系 -->
        <link name="depth"/>
        <joint name="depth_joint" type="fixed">
            <origin xyz="0 0 0" rpy="-1.57 0 -1.57"/>
            <parent link="rgb"/>
            <child link="depth"/>
        </joint>

        2、把相机插件中的<frameName>rgb</frameName>参数改为<frameName>depth</frameName>

        <gazebo reference="rgb">
            <sensor type="depth" name="camera">
                <always_on>true</always_on>
                <update_rate>20</update_rate>
                <camera>
                    <horizontal_fov>${60.0 * PI/ 180.0}</horizontal_fov>
                    <image>
                        <width>640</width>
                        <height>480</height>
                        <format>R8G8B8</format>
                    </image>
                    <clip>
                        <near>0.05</near>
                        <far>15.0</far>
                    </clip>
                </camera>
                <plugin name="kinect_camera_controller" filename="libgazebo_ros_openni_kinect.so">
                    <cameraName>camera</cameraName>
                    <alwaysOn>true</alwaysOn>
                    <updateRate>10</updateRate>
                    <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>rgb</frameName> <!-- 把这个rgb改为depth -->
                    <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>

改正后,点云效果:

六、结语

        我们虽然越过了大问题,但是茫茫仿真开发路才开始,我们还要加油去探索。

        后面如果需要加其他插件,我们需要修改我们自己的源模型描述文件,仿照第五大点去配置自己的其他仿真驱动插件。

七、附页

关于附加机械爪的仿真:

        其实和上述的机械臂仿真差不多(我就不详细介绍了),我们需要准备机械爪的urdf文件,把他和机械的link用joint连接起来,之后再用moveit配置软件开始配置,与上面不同的地方有以下一些。

1、继续添加组

 2、添加控制组的joint

3、添加姿态

4、添加控制器

基本上 就是这些操作,具体的可以仿照上文机械臂的配置

关于gazebo仿真夹爪出现抖动的问题,我用下文来说明:

ROS下gazebo仿真夹爪抖动问题-CSDN博客

### 如何在Gazebo中使用MoveIt #### 配置环境与安装依赖项 为了使 MoveItGazebo 能够协同工作,需先配置好 ROS (Robot Operating System) 的开发环境并安装必要的软件包。这通常涉及设置 ROS 工作空间以及通过 `apt` 或者源码编译的方式获取最新本的 MoveIt! 和 Gazebo[^1]。 ```bash sudo apt-get update && sudo apt-get install ros-noetic-moveit ros-noetic-gazebo-ros-pkgs ``` #### 创建机器人模型文件 对于特定类型的机械臂如 Universal Robots 5 (UR5),应该准备相应的 URDF 文件来描述其物理属性和运动学参数。这些信息可以用来初始化仿真环境中机器人的状态,并确保两者之间的交互正常运作。 #### 启动Gazebo世界与加载机器人 启动一个自定义构建好的 Gazebo 场景之后,可以通过命令行工具将 UR5 加载到该场景当中: ```bash roslaunch ur_gazebo ur5.launch ``` 此时,在终端窗口内会显示有关于成功连接至模拟器的消息提示;与此同时,另一个新的图形界面将会弹出展示当前所处的工作区状况。 #### 设置MoveIt规划组及其约束条件 接下来要的就是为即将执行的任务指定一组关节作为操作对象——即所谓的“Planning Group”。此过程涉及到编辑 YAML 格式的配置文档以适应具体的应用需求。例如设定末端效应器的位置范围或是避开某些障碍物等特殊要求。 #### 运行MoveIt插件实现控制功能 最后一步便是利用 RViz 中集成有专门针对 MoveIt 设计的功能模块来进行路径规划及可视化调试。当一切就绪后,只需简单点击几下鼠标即可发送指令给虚拟平台上的设备完成预期动作序列。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值