ROS2与gazebo联合仿真自定义机械臂(ros2_control)

1. 准备实际的三维模型文件(stl二进制格式的)

2. 编写机械臂的urdf文件,也可以改装为xacro文件\

<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="r6bot">
    <xacro:property name="ModelPathHead"
        value="file://"到机械臂三维模型的绝对路径" />
    <xacro:property name="pi" value="3.1415926" />
    <link name="base_link">
        <visual>
            <geometry>
                <mesh filename="${ModelPathHead}link_0.stl" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="Red">
                <color rgba="1 0 0 1" />
            </material>
        </visual>
        <collision>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <mesh filename="${ModelPathHead}link_0.stl" />
            </geometry>
        </collision>
        <inertial>
            <mass value="1" />
            <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" />
        </inertial>
    </link>

    <link name="link_1">
        <visual>
            <geometry>
                <mesh filename="${ModelPathHead}link_1.stl" />
            </geometry>
            <origin rpy="0 0 0" xyz="0 0 0" />
            <material name="Red">
                <color rgba="1 0 0 1" />
            </material>
        </visual>
        <collision>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <mesh filename="${ModelPathHead}link_1.stl" />
            </geometry>
        </collision>
        <inertial>
            <mass value="1" />
            <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" />
        </inertial>
    </link>

    <link name="link_2">
        <visual>
            <geometry>
                <mesh filename="${ModelPathHead}link_2.stl" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="red">
                <color rgba="1 0 0 1" />
            </material>
        </visual>
        <collision>
            <origin xyx="0 0 0" rpy="0 0 0" />
            <geometry>
                <mesh filename="${ModelPathHead}link_2.stl" />
            </geometry>
        </collision>
        <inertial>
            <mass value="1" />
            <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" />
        </inertial>
    </link>

    <link name="link_3">
        <visual>
            <geometry>
                <mesh filename="${ModelPathHead}link_3.stl" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="Red">
                <color rgba="1 0 0 1" />
            </material>
        </visual>
        <collision>
            <origin xyx="0 0 0" rpy="0 0 0" />
            <geometry>
                <mesh filename="${ModelPathHead}link_3.stl" />
            </geometry>
        </collision>
        <inertial>
            <mass value="1" />
            <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" />
        </inertial>
    </link>

    <link name="link_4">
        <visual>
            <geometry>
                <mesh filename="${ModelPathHead}link_4.stl" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="Red">
                <color rgba="1 0 0 1" />
            </material>
        </visual>
        <collision>
            <origin xyx="0 0 0" rpy="0 0 0" />
            <geometry>
                <mesh filename="${ModelPathHead}link_4.stl" />
            </geometry>
        </collision>
        <inertial>
            <mass value="1" />
            <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" />
        </inertial>
    </link>

    <link name="link_5">
        <visual>
            <geometry>
                <mesh filename="${ModelPathHead}link_5.stl" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="Red">
                <color rgba="1 0 0 1" />
            </material>
        </visual>
        <collision>
            <origin xyx="0 0 0" rpy="0 0 0" />
            <geometry>
                <mesh filename="${ModelPathHead}link_5.stl" />
            </geometry>
        </collision>
        <inertial>
            <mass value="1" />
            <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" />
        </inertial>
    </link>

    <link name="link_6">
        <visual>
            <geometry>
                <mesh filename="${ModelPathHead}link_6.stl" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="Red">
                <color rgba="1 0 0 1" />
            </material>
        </visual>
        <collision>
            <origin xyx="0 0 0" rpy="0 0 0" />
            <geometry>
                <mesh filename="${ModelPathHead}link_6.stl" />
            </geometry>
        </collision>
        <inertial>
            <mass value="1" />
            <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" />
        </inertial>
    </link>

    <!-- <link name="world"/> -->

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

  <!-- joints - main serial chain -->
    <joint name="Joint_1" type="revolute">
        <parent link="base_link" />
        <child link="link_1" />
        <origin xyz="0 0 0.061584" rpy="0 0 0" />
        <axis xyz="0 0 1" />
        <limit effort="1000.0" lower="${-pi}" upper="${pi}" velocity="2.5" />
    </joint>

    <joint name="Joint_2" type="revolute">
        <parent link="link_1" />
        <child link="link_2" />
        <origin xyz="-0.101717 0 0.182284" rpy="${-pi/2} -${pi/3} ${pi/2}" />
        <axis xyz="0 0 1" />
        <limit effort="1000.0" lower="${-pi}" upper="${pi}" velocity="2.5" />
    </joint>

    <joint name="Joint_3" type="revolute">
        <parent link="link_2" />
        <child link="link_3" />
        <origin xyz="0.685682 0 0.041861" rpy="0 ${pi} ${pi+pi/2}" />
        <axis xyz="0 0 1" />
        <limit effort="1000.0" lower="${-pi}" upper="${pi}" velocity="2.5" />
    </joint>

    <joint name="Joint_4" type="revolute">
        <parent link="link_3" />
        <child link="link_4" />
        <origin xyz="0.518777 0 0.067458" rpy="0 ${pi} ${pi+pi/6}" />
        <axis xyz="0 0 1" />
        <limit effort="1000.0" lower="${-pi}" upper="${pi}" velocity="2.5" />
    </joint>

    <joint name="Joint_5" type="revolute">
        <parent link="link_4" />
        <child link="link_5" />
        <origin xyz="0.112654 0 0.110903" rpy="${pi/2} ${pi} ${pi/2}" />
        <axis xyz="0 0 1" />
        <limit effort="1000.0" lower="${-pi}" upper="${pi}" velocity="2.5" />
    </joint>

    <joint name="Joint_6" type="revolute">
        <parent link="link_5" />
        <child link="link_6" />
        <origin xyz="-0.085976 0 0.133436" rpy="0 ${-pi/2} 0" />
        <axis xyz="0 0 1" />
        <limit effort="1000.0" lower="${-pi}" upper="${pi}" velocity="2.5" />
    </joint>


    <gazebo reference="base_link">
        <material>Gazebo/Purple</material>
        <self_collide>false</self_collide>
        <gravity>false</gravity>
    </gazebo>

    <gazebo reference="link_1">
        <material>Gazebo/Purple</material>
        <self_collide>false</self_collide>
        <gravity>false</gravity>
    </gazebo>

    <gazebo reference="link_2">
        <material>Gazebo/Purple</material>
        <self_collide>false</self_collide>
        <gravity>false</gravity>
    </gazebo>

    <gazebo reference="link_3">
        <material>Gazebo/Purple</material>
        <self_collide>false</self_collide>
        <gravity>false</gravity>
    </gazebo>

    <gazebo reference="link_4">
        <material>Gazebo/Purple</material>
        <self_collide>false</self_collide>
        <gravity>false</gravity>
    </gazebo>

    <gazebo reference="link_5">
        <material>Gazebo/Purple</material>
        <self_collide>false</self_collide>
        <gravity>false</gravity>
    </gazebo>

    <gazebo reference="link_6">
        <material>Gazebo/Purple</material>
        <self_collide>false</self_collide>
        <gravity>false</gravity>
    </gazebo>

</robot>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="Staubli">
    <xacro:property name="UrdfPathHead" value="urdf文件路径" />
    <!-- <xacro:include filename="${UrdfPathHead}robot.urdf.xacro" /> -->
    <link name="world" />
    <xacro:include filename="${UrdfPathHead}r6bot.urdf.xacro" />

    <xacro:include filename="${UrdfPathHead}robot_ros_control.urdf.xacro" />
</robot>

3.编写控制文件(xacro)

<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="Staubli" >
    <ros2_control name="GazeboSystem" type="system">
        <hardware>
          <plugin>gazebo_ros2_control/GazeboSystem</plugin>
        </hardware>
        
        <joint name="Joint_1">
            <command_interface name="position" />
            <state_interface name="position"/>
            <state_interface name="velocity"/>
        </joint>

        <joint name="Joint_2">
            <command_interface name="position" />
            <state_interface name="position"/>
            <state_interface name="velocity"/>
        </joint>

        <joint name="Joint_3">
            <command_interface name="position" />
            <state_interface name="position"/>
            <state_interface name="velocity"/>
        </joint>

        <joint name="Joint_4">
            <command_interface name="position" />
            <state_interface name="position"/>
            <state_interface name="velocity"/>
        </joint>

        <joint name="Joint_5">
            <command_interface name="position" />
            <state_interface name="position"/>
            <state_interface name="velocity"/>
        </joint>

        <joint name="Joint_6">
            <command_interface name="position" />
            <state_interface name="position"/>
            <state_interface name="velocity"/>
        </joint>
    </ros2_control>

    <gazebo>
      <plugin filename="libgazebo_ros2_control.so" name="gazebo_ros2_control">
        <!-- 这个是编写的控制器文件的路径 -->
          <parameters>$(find gazebo_robot)/config/gazebo_robot_control.yaml</parameters>
      </plugin>
  </gazebo>

</robot>

4. 定义控制器

controller_manager:
  ros__parameters:
    update_rate: 100
    sue_sim_time: true

    arm_controller:
      type: position_controllers/JointGroupPositionController // ros2_control 里面定义的控制器

    joint_state_broadcaster:
      type: joint_state_broadcaster/JointStateBroadcaster   //固定的

arm_controller:
  ros__parameters:
    joints:
      - Joint_1  // 注意和机械臂的urdf中定义的关节角保持一致
      - Joint_2
      - Joint_3
      - Joint_4
      - Joint_5
      - Joint_6
    command_interface:
      - position

    state_interface:
      - position
      - velocity

5.编写launch文件

import os
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, ExecuteProcess,RegisterEventHandler
from launch_ros.substitutions import FindPackageShare
from launch_ros.actions import Node
from launch.substitutions import Command
from launch.event_handlers import OnProcessExit
import launch.actions
import xacro



def generate_launch_description():
    robot_name_in_model ="r6bot"
    package_name='gazebo_robot'
    urdf_name = "r6bot_main.urdf.xacro"
    ld = LaunchDescription()
    #找到自己的ros包
    pkg_share = FindPackageShare(package='gazebo_robot').find('gazebo_robot')
    urdf_model_path = os.path.join(pkg_share, f'urdf/{urdf_name}')

    start_gazebo_cmd =  ExecuteProcess(
        cmd=['gazebo', '--verbose','-s', 'libgazebo_ros_init.so', '-s', 'libgazebo_ros_factory.so'],
        output='screen')
    
    doc = xacro.parse(open(urdf_model_path))
    xacro.process_doc(doc)
    params = {'robot_description': doc.toxml()}
    

    node_robot_state_publisher = Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        output='screen',
        parameters=[params]
    )

    # Launch the robot
    spawn_entity_cmd = Node(
        package='gazebo_ros', 
        executable='spawn_entity.py',
        arguments=['-topic', 'robot_description','-entity', 'robot_gazebo'], output='screen')
    

#将自己定义的环境模型,写成类似与gazebo自带的模型文件形式,注意有几个文件定义。
#自己如何撰写gazebo模型,可以参考网上的教程 最后需要export路径,这里用python实现
    model_path = 自定义的模型文件的路径"

    if "GAZEBO_MODEL_PATH" in os.environ:
        os.environ["GAZEBO_MODEL_PATH"] += ":" + model_path
    else:
        os.environ["GAZEBO_MODEL_PATH"] = model_path
    EnvModel = Node(
        package='gazebo_ros', 
        executable='spawn_entity.py',
#'.sdf文件路径'是自定义模型中有个sdf文件的,直接传入这个文件的路径。
        arguments=['-entity', 'demo', '-file', '.sdf文件路径'], output='screen')
    
    
    joint_broad_spawner = Node(
        package="controller_manager",
        executable="spawner",
        arguments=["joint_state_broadcaster"]
    )

    arm_broad_spawner=Node(
        package="controller_manager",
        executable="spawner",
        arguments=["arm_controller"]
    )

    ld.add_action(start_gazebo_cmd)
    ld.add_action(node_robot_state_publisher)
    ld.add_action(spawn_entity_cmd)
    ld.add_action(EnvModel)
    ld.add_action(joint_broad_spawner)
    ld.add_action(arm_broad_spawner)

    return ld

后续把这部分实际代码分享到git中。路径:Ros2_Control: Ros2与gazebo联合仿真

MoveIt是一个功能强大的机器人操作系统(ROS)插件,用于规划和控制机械臂运动。它为机械臂提供了运动规划、逆运动学解算、碰撞检测等功能,使得机械臂能够在复杂的环境进行精确和安全的移动。MoveIt使用了先进的运动规划算法,包括RRT、OMPL等,能够快速找到机械臂的运动轨迹。 Gazebo是一个用于仿真机器人和环境的开源物理仿真器。它模拟了机器人在现实世界的动力学和物理特性,包括重力、摩擦力等。使用Gazebo,我们可以在虚拟环境进行机器人的开发、测试和验证。Gazebo机器人的模型和控制器与MoveIt集成,可以实现机械臂的运动仿真和控制。 MoveIt和Gazebo的结合可以提供一个完整的机械臂开发和仿真环境。首先,我们可以使用MoveIt规划机械臂的运动轨迹,并将其发送给Gazebo进行仿真。在仿真,我们可以观察机械臂在不同环境的运动情况,并进行调试和优化。同时,Gazebo还可以提供机器人周围环境的传感器数据,用于机械臂的感知和决策。 此外,MoveIt还支持与真实物理机械臂的集成。我们可以将规划好的轨迹发送给真实机械臂控制器,实现机械臂的精确控制。通过在实际环境运行和测试机械臂,我们可以验证算法的正确性和鲁棒性。 综上所述,MoveIt和Gazebo机械臂提供了一个全面而强大的解决方案,用于机械臂的规划、运动仿真和控制。它们的结合使得机械臂的开发过程更加高效和可靠,并为机器人研究和应用提供了强大的工具。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值