Chapter4:机器人仿真

news2024/11/25 23:33:11

R O S 1 {\rm ROS1} ROS1的基础及应用,基于古月的课,各位可以去看,基于 h a w k b o t {\rm hawkbot} hawkbot机器人进行实际操作。
R O S {\rm ROS} ROS版本: R O S 1 {\rm ROS1} ROS1 M e l o d i c {\rm Melodic} Melodic;实际机器人: H a w k b o t {\rm Hawkbot} Hawkbot



1.机器人URDF模型优化

  1. U R D F {\rm URDF} URDF模型进化版本– x a c r o {\rm xacro} xacro模型文件

    1. 精简模型代码
      • 创建宏定义;
      • 文件包含;
    2. 提供可编程接口
      • 常量;
      • 变量;
      • 数学计算;
      • 条件语句;
  2. 常量定义

    # 常量定义
    <xacro:property name="M_PI" value="3.14159" />
    
    # 常量使用
    <origin xyz="0 0 0" ryp="${M_PI/2} 0 0" />
    
  3. 数学计算

    # 数学计算
    <origin xyz="0 ${(motor_length+wheel_length)/2} 0" rpy="0 0 0"/>
    
  4. 宏定义

    # 宏定义
    <xacro:macro name="name" params="A B C">
    ...
    </xacro:macro>
    
    # 宏调用
    <name A="A_value" B="B_value" C="C_value" />
    
  5. 文件包含

    # 文件包含
    <xacro:include filename="$(find mbot_description)/urdf/xacro/mbot_base.xacro" />
    

2.使用xacro建立模型

# 1.在urdf文件夹下建立xacro文件夹
mkdir xacro

# 在xacro目录下新建mbot_base.xacro和mbot.xacro文件
# 文件内容见下个代码块,请勿直接复制粘贴
touch mbot_base.xacro mbot.xacro

# 2.新建display_mbot_base_xacro.launch文件
# 文件内容见下个代码块,请勿直接复制粘贴
touch display_mbot_base_xacro.launch

# 3.模型显示
# 法1:将xacro文件转换成URDF文件显示
rosrun xacro xacro.py mbot.xacro > mbot.urdf

# 法2:直接调用xacro文件解析器,在.launch文件中写入
<arg name="model" default="$(find xacro)/xacro--inorder'$(find mbot_description)/urdf/xacro/mbot.xacro'" />

<param name="robot_description" command="$(arg model)" />

# 4.启动.launch文件
roslaunch mbot_description display_mbot_base_xacro.launch
# mbot_base.xacro文件内容
<?xml version="1.0"?>
<robot name="mbot" xmlns:xacro="http://www.ros.org/wiki/xacro">

    <!-- PROPERTY LIST -->
    <xacro:property name="M_PI" value="3.1415926"/>
    <xacro:property name="base_radius" value="0.20"/>
    <xacro:property name="base_length" value="0.16"/>

    <xacro:property name="wheel_radius" value="0.06"/>
    <xacro:property name="wheel_length" value="0.025"/>
    <xacro:property name="wheel_joint_y" value="0.19"/>
    <xacro:property name="wheel_joint_z" value="0.05"/>

    <xacro:property name="caster_radius" value="0.015"/> <!-- wheel_radius - ( base_length/2 - wheel_joint_z) -->
    <xacro:property name="caster_joint_x" value="0.18"/>

    <!-- Defining the colors used in this robot -->
    <material name="yellow">
        <color rgba="1 0.4 0 1"/>
    </material>
    <material name="black">
        <color rgba="0 0 0 0.95"/>
    </material>
    <material name="gray">
        <color rgba="0.75 0.75 0.75 1"/>
    </material>
    
    <!-- Macro for robot wheel -->
    <xacro:macro name="wheel" params="prefix reflect">
        <joint name="${prefix}_wheel_joint" type="continuous">
            <origin xyz="0 ${reflect*wheel_joint_y} ${-wheel_joint_z}" rpy="0 0 0"/>
            <parent link="base_link"/>
            <child link="${prefix}_wheel_link"/>
            <axis xyz="0 1 0"/>
        </joint>

        <link name="${prefix}_wheel_link">
            <visual>
                <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" />
                <geometry>
                    <cylinder radius="${wheel_radius}" length = "${wheel_length}"/>
                </geometry>
                <material name="gray" />
            </visual>
        </link>
    </xacro:macro>

    <!-- Macro for robot caster -->
    <xacro:macro name="caster" params="prefix reflect">
        <joint name="${prefix}_caster_joint" type="continuous">
            <origin xyz="${reflect*caster_joint_x} 0 ${-(base_length/2 + caster_radius)}" rpy="0 0 0"/>
            <parent link="base_link"/>
            <child link="${prefix}_caster_link"/>
            <axis xyz="0 1 0"/>
        </joint>

        <link name="${prefix}_caster_link">
            <visual>
                <origin xyz="0 0 0" rpy="0 0 0"/>
                <geometry>
                    <sphere radius="${caster_radius}" />
                </geometry>
                <material name="black" />
            </visual>
        </link>
    </xacro:macro>

    <xacro:macro name="mbot_base">
        <link name="base_footprint">
            <visual>
                <origin xyz="0 0 0" rpy="0 0 0" />
                <geometry>
                    <box size="0.001 0.001 0.001" />
                </geometry>
            </visual>
        </link>

        <joint name="base_footprint_joint" type="fixed">
            <origin xyz="0 0 ${base_length/2 + caster_radius*2}" rpy="0 0 0" />        
            <parent link="base_footprint"/>
            <child link="base_link" />
        </joint>

        <link name="base_link">
            <visual>
                <origin xyz=" 0 0 0" rpy="0 0 0" />
                <geometry>
                    <cylinder length="${base_length}" radius="${base_radius}"/>
                </geometry>
                <material name="yellow" />
            </visual>
        </link>

        <wheel prefix="left" reflect="-1"/>
        <wheel prefix="right" reflect="1"/>

        <caster prefix="front" reflect="-1"/>
        <caster prefix="back" reflect="1"/>
    </xacro:macro>
</robot>
# mbot.xacro文件内容
<?xml version="1.0"?>
<robot name="arm" xmlns:xacro="http://www.ros.org/wiki/xacro">

    <xacro:include filename="$(find mbot_description)/urdf/xacro/mbot_base.xacro" />

    <mbot_base/>

</robot>
# display_mbot_base_xacro.launch文件内容
<launch>
	<arg name="model" default="$(find xacro)/xacro --inorder '$(find mbot_description)/urdf/xacro/mbot.xacro'" />
	<arg name="gui" default="true" />

	<param name="robot_description" command="$(arg model)" />

    <!-- 设置GUI参数,显示关节控制插件 -->
	<param name="use_gui" value="$(arg gui)"/>

    <!-- 运行joint_state_publisher节点,发布机器人的关节状态  -->
	<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />

	<!-- 运行robot_state_publisher节点,发布tf  -->
	<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />

    <!-- 运行rviz可视化界面 -->
	<node name="rviz" pkg="rviz" type="rviz" args="-d $(find mbot_description)/config/mbot.rviz" required="true" />

</launch>

3.ArbotiX+rviz功能仿真

  1. A r b o t i X {\rm ArbotiX} ArbotiX简介

    • 一款控制电机、舵机的硬件控制板;
    • 提供了相应的 R O S {\rm ROS} ROS功能包;
    • 提供了一个差速控制器,通过接收速度控制指令,更新机器人的里程计状态;
  2. A r b o t i X {\rm ArbotiX} ArbotiX安装

    # ros相关信息:Ubuntu 18.04+melodic
    # 1.下载ArbotiX功能包
    cd willard_ws/src/
    git clone -b indigo-devel
    https://github.com/vanadiumlabs/arbotix_ros.git
    
    # 2.工作空间下编译
    cd ~/willard_ws/
    catkin_make
    
    
  3. 配置 A r b o t i X {\rm ArbotiX} ArbotiX控制器

    # 1.创建launch文件
    cd willard_ws/src/mbot_description/launch/xacro/
    
    # 文件内容见下个代码块,请勿直接复制粘贴
    touch arbotix_mbot_with_camera_xacro.launch
    
    # 2.创建配置文件
    cd willard_ws/src/mbot_description/config/
    
    # 文件内容见下个代码块,请勿直接复制粘贴
    touch fake_mbot_arbotix.yaml
    
    # 3.启动仿真器
    roslaunch mbot_description arbotix_mbot_with_camera_xacro.launch
    
    # 4.键盘控制相关
    # 4.1 新建mbot_teleop功能包
    catkin_create_pkg willard_teleop roscpp std_msgs rospy
    
    # 4.2 在willard_teleop下创建launch、scripts文件夹
    mkdir launch scripts
    
    # 4.3 在/scripts文件夹下创建.py文件
    # 文件内容见下个代码块,请勿直接复制粘贴
    touch willard_teleop.py
    
    # 4.4 给.py文件添加可执行权限
    chmod 777 willard_teleop.py
    
    # 4.5 新建.launch文件
    # 文件内容见下个代码块,请勿直接复制粘贴
    touch willard_teleop.launch 
    
    # 5.启动键盘控制
    roslaunch willard_teleop willard_teleop.launch
    
    
    # arbotix_mbot_with_camera_xacro.launch文件内容
    <launch>
    	<arg name="model" default="$(find xacro)/xacro --inorder '$(find mbot_description)/urdf/xacro/mbot_with_camera.xacro'" />
    	<arg name="gui" default="false" />
    
    	<param name="robot_description" command="$(arg model)" />
    
        <!-- 设置GUI参数,显示关节控制插件 -->
    	<param name="use_gui" value="$(arg gui)"/>
    
    	<node name="arbotix" pkg="arbotix_python" type="arbotix_driver" output="screen">
            <rosparam file="$(find mbot_description)/config/fake_mbot_arbotix.yaml" command="load" />
            <param name="sim" value="true"/>
        </node>
    
        <!-- 运行joint_state_publisher节点,发布机器人的关节状态  -->
    	<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
    
    	<!-- 运行robot_state_publisher节点,发布tf  -->
    	<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
    
        <!-- 运行rviz可视化界面 -->
    	<node name="rviz" pkg="rviz" type="rviz" args="-d $(find mbot_description)/config/mbot_arbotix.rviz" required="true" />
    
    </launch>
    
    
    # fake_mbot_arbotix.yaml文件内容
    controllers: {
       base_controller: {
           type: diff_controller, 
           base_frame_id: base_footprint, 
           base_width: 0.26, 
           ticks_meter: 4100, 
           Kp: 12, 
           Kd: 12, 
           Ki: 0, 
           Ko: 50, 
           accel_limit: 1.0 
        }
    }
    
    
    # willard_teleop.py文件内容
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import rospy
    from geometry_msgs.msg import Twist
    import sys, select, termios, tty
    
    msg = """
    Control mbot!
    ---------------------------
    Moving around:
       u    i    o
       j    k    l
       m    ,    .
    
    q/z : increase/decrease max speeds by 10%
    w/x : increase/decrease only linear speed by 10%
    e/c : increase/decrease only angular speed by 10%
    space key, k : force stop
    anything else : stop smoothly
    
    CTRL-C to quit
    """
    
    moveBindings = {
            'i':(1,0),
            'o':(1,-1),
            'j':(0,1),
            'l':(0,-1),
            'u':(1,1),
            ',':(-1,0),
            '.':(-1,1),
            'm':(-1,-1),
               }
    
    speedBindings={
            'q':(1.1,1.1),
            'z':(.9,.9),
            'w':(1.1,1),
            'x':(.9,1),
            'e':(1,1.1),
            'c':(1,.9),
              }
    
    def getKey():
        tty.setraw(sys.stdin.fileno())
        rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
        if rlist:
            key = sys.stdin.read(1)
        else:
            key = ''
    
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
        return key
    
    speed = .2
    turn = 1
    
    def vels(speed,turn):
        return "currently:\tspeed %s\tturn %s " % (speed,turn)
    
    if __name__=="__main__":
        settings = termios.tcgetattr(sys.stdin)
        
        rospy.init_node('mbot_teleop')
        pub = rospy.Publisher('/cmd_vel', Twist, queue_size=5)
    
        x = 0
        th = 0
        status = 0
        count = 0
        acc = 0.1
        target_speed = 0
        target_turn = 0
        control_speed = 0
        control_turn = 0
        try:
            print msg
            print vels(speed,turn)
            while(1):
                key = getKey()
                # 运动控制方向键(1:正方向,-1负方向)
                if key in moveBindings.keys():
                    x = moveBindings[key][0]
                    th = moveBindings[key][1]
                    count = 0
                # 速度修改键
                elif key in speedBindings.keys():
                    speed = speed * speedBindings[key][0]  # 线速度增加0.1倍
                    turn = turn * speedBindings[key][1]    # 角速度增加0.1倍
                    count = 0
    
                    print vels(speed,turn)
                    if (status == 14):
                        print msg
                    status = (status + 1) % 15
                # 停止键
                elif key == ' ' or key == 'k' :
                    x = 0
                    th = 0
                    control_speed = 0
                    control_turn = 0
                else:
                    count = count + 1
                    if count > 4:
                        x = 0
                        th = 0
                    if (key == '\x03'):
                        break
    
                # 目标速度=速度值*方向值
                target_speed = speed * x
                target_turn = turn * th
    
                # 速度限位,防止速度增减过快
                if target_speed > control_speed:
                    control_speed = min( target_speed, control_speed + 0.02 )
                elif target_speed < control_speed:
                    control_speed = max( target_speed, control_speed - 0.02 )
                else:
                    control_speed = target_speed
    
                if target_turn > control_turn:
                    control_turn = min( target_turn, control_turn + 0.1 )
                elif target_turn < control_turn:
                    control_turn = max( target_turn, control_turn - 0.1 )
                else:
                    control_turn = target_turn
    
                # 创建并发布twist消息
                twist = Twist()
                twist.linear.x = control_speed; 
                twist.linear.y = 0; 
                twist.linear.z = 0
                twist.angular.x = 0; 
                twist.angular.y = 0; 
                twist.angular.z = control_turn
                pub.publish(twist)
    
        except:
            print e
    
        finally:
            twist = Twist()
            twist.linear.x = 0; twist.linear.y = 0; twist.linear.z = 0
            twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = 0
            pub.publish(twist)
    
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
    
    
    # willard_teleop.launch
    <launch>
      <node name="willard_teleop" pkg="willard_teleop" type="willard_teleop.py" output="screen">
        <param name="scale_linear" value="0.1" type="double"/>
        <param name="scale_angular" value="0.4" type="double"/>
      </node>
    </launch>
    
    
  4. 仿真效果图

    1

4.Gazebo物理仿真环境搭建

4.1 ros_control
  1. r o s _ c o n t r o l {\rm ros\_control} ros_control简介

    • R O S {\rm ROS} ROS为开发者提供的机器人控制中间件;
    • 包含一系列控制器接口、传动装置接口、硬件接口、控制器工具等;
    • 可以帮助机器人应用功能包快速落地,提高开发效率;
  2. r o s _ c o n t r o l {\rm ros\_control} ros_control框架

    2

    3

    • 控制器管理器:提供一种通用的接口来管理不同的控制器;
    • 控制器:读取硬件状态,发布控制命令,完成每个 j o i n t {\rm joint} joint的控制;
    • 硬件资源:为上下两层提供硬件资源的接口;
    • 机器人硬件抽象:机器人硬件抽象和硬件资源直接打交道,通过 w r i t e {\rm write} write r e a d {\rm read} read方法完成硬件操作;
    • 真实机器人:执行接收到的命令;

    4

  3. 控制器 ( c o n t r o l l e r s ) ({\rm controllers}) (controllers)介绍

    5

4.2 仿真步骤
  1. 配置机器人模型;
  2. 创建仿真环境;
  3. 开始仿真;
4.2.1 配置物理仿真模型
  • S T E P 1 {\rm STEP1} STEP1:为 l i n k {\rm link} link添加惯性参数和碰撞属性;
  • S T E P 2 {\rm STEP2} STEP2:为 l i n k {\rm link} link添加 g a z e b o {\rm gazebo} gazebo标签;
  • S T E P 3 {\rm STEP3} STEP3:为 j o i n t {\rm joint} joint添加传动装置;
  • S T E P 4 {\rm STEP4} STEP4:添加 g a z e b o {\rm gazebo} gazebo控制器插件;
    • < r o b o t N a m e s p a c e {\rm robotNamespace} robotNamespace>:机器人的命名空间;
    • < l e f t J o i n t {\rm leftJoint} leftJoint>和< r i g h t J o i n t {\rm rightJoint} rightJoint>:左右轮转动的关节 j o i n t {\rm joint} joint
    • < w h e e l S e p a r a t i o n {\rm wheelSeparation} wheelSeparation>和< w h e e l D i a m e t e r {\rm wheelDiameter} wheelDiameter>:机器人模型的相关尺寸,在计算差速参数时需要使用;
    • < c o m m a n d T o p i c {\rm commandTopic} commandTopic>:控制器订阅的速度控制指令,生成全局命名时需要结合< r o b o t N a m e s p a c e {\rm robotNamespace} robotNamespace>中设置的命名空间;
    • < o d o m e t r y F r a m e {\rm odometryFrame} odometryFrame>:里程计数据的参考坐标系, R O S {\rm ROS} ROS中一般命名为 o d o m {\rm odom} odom

物理仿真模型配置实例:

# mbot_base_gazebo.xacro文件内容

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

    <!-- PROPERTY LIST -->
    <xacro:property name="M_PI" value="3.1415926"/>
    <xacro:property name="base_mass"   value="20" /> 
    <xacro:property name="base_radius" value="0.20"/>
    <xacro:property name="base_length" value="0.16"/>

    <xacro:property name="wheel_mass"   value="2" />
    <xacro:property name="wheel_radius" value="0.06"/>
    <xacro:property name="wheel_length" value="0.025"/>
    <xacro:property name="wheel_joint_y" value="0.19"/>
    <xacro:property name="wheel_joint_z" value="0.05"/>

    <xacro:property name="caster_mass"    value="0.5" /> 
    <xacro:property name="caster_radius"  value="0.015"/> <!-- wheel_radius - ( base_length/2 - wheel_joint_z) -->
    <xacro:property name="caster_joint_x" value="0.18"/>

    <!-- Defining the colors used in this robot -->
    <material name="yellow">
        <color rgba="1 0.4 0 1"/>
    </material>
    <material name="black">
        <color rgba="0 0 0 0.95"/>
    </material>
    <material name="gray">
        <color rgba="0.75 0.75 0.75 1"/>
    </material>
    
    <!-- Macro for inertia matrix -->
    <xacro:macro name="sphere_inertial_matrix" params="m r">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${2*m*r*r/5}" ixy="0" ixz="0"
                iyy="${2*m*r*r/5}" iyz="0" 
                izz="${2*m*r*r/5}" />
        </inertial>
    </xacro:macro>

    <xacro:macro name="cylinder_inertial_matrix" params="m r h">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${m*(3*r*r+h*h)/12}" ixy = "0" ixz = "0"
                iyy="${m*(3*r*r+h*h)/12}" iyz = "0"
                izz="${m*r*r/2}" /> 
        </inertial>
    </xacro:macro>

    <!-- Macro for robot wheel -->
    <xacro:macro name="wheel" params="prefix reflect">
        <joint name="${prefix}_wheel_joint" type="continuous">
            <origin xyz="0 ${reflect*wheel_joint_y} ${-wheel_joint_z}" rpy="0 0 0"/>
            <parent link="base_link"/>
            <child link="${prefix}_wheel_link"/>
            <axis xyz="0 1 0"/>
        </joint>

        <link name="${prefix}_wheel_link">
            <visual>
                <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" />
                <geometry>
                    <cylinder radius="${wheel_radius}" length = "${wheel_length}"/>
                </geometry>
                <material name="gray" />
            </visual>
            <collision>
                <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" />
                <geometry>
                    <cylinder radius="${wheel_radius}" length = "${wheel_length}"/>
                </geometry>
            </collision>
            <cylinder_inertial_matrix  m="${wheel_mass}" r="${wheel_radius}" h="${wheel_length}" />
        </link>

        <gazebo reference="${prefix}_wheel_link">
            <material>Gazebo/Gray</material>
        </gazebo>

        <!-- Transmission is important to link the joints and the controller -->
        <transmission name="${prefix}_wheel_joint_trans">
            <type>transmission_interface/SimpleTransmission</type>
            <joint name="${prefix}_wheel_joint" >
                <hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
            </joint>
            <actuator name="${prefix}_wheel_joint_motor">
                <hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
                <mechanicalReduction>1</mechanicalReduction>
            </actuator>
        </transmission>
    </xacro:macro>

    <!-- Macro for robot caster -->
    <xacro:macro name="caster" params="prefix reflect">
        <joint name="${prefix}_caster_joint" type="continuous">
            <origin xyz="${reflect*caster_joint_x} 0 ${-(base_length/2 + caster_radius)}" rpy="0 0 0"/>
            <parent link="base_link"/>
            <child link="${prefix}_caster_link"/>
            <axis xyz="0 1 0"/>
        </joint>

        <link name="${prefix}_caster_link">
            <visual>
                <origin xyz="0 0 0" rpy="0 0 0"/>
                <geometry>
                    <sphere radius="${caster_radius}" />
                </geometry>
                <material name="black" />
            </visual>
            <collision>
                <origin xyz="0 0 0" rpy="0 0 0"/>
                <geometry>
                    <sphere radius="${caster_radius}" />
                </geometry>
            </collision>      
            <sphere_inertial_matrix  m="${caster_mass}" r="${caster_radius}" />
        </link>

        <gazebo reference="${prefix}_caster_link">
            <material>Gazebo/Black</material>
        </gazebo>
    </xacro:macro>

    <xacro:macro name="mbot_base_gazebo">
        <link name="base_footprint">
            <visual>
                <origin xyz="0 0 0" rpy="0 0 0" />
                <geometry>
                    <box size="0.001 0.001 0.001" />
                </geometry>
            </visual>
        </link>
        <gazebo reference="base_footprint">
            <turnGravityOff>false</turnGravityOff>
        </gazebo>

        <joint name="base_footprint_joint" type="fixed">
            <origin xyz="0 0 ${base_length/2 + caster_radius*2}" rpy="0 0 0" />        
            <parent link="base_footprint"/>
            <child link="base_link" />
        </joint>

        <link name="base_link">
            <visual>
                <origin xyz=" 0 0 0" rpy="0 0 0" />
                <geometry>
                    <cylinder length="${base_length}" radius="${base_radius}"/>
                </geometry>
                <material name="yellow" />
            </visual>
            <collision>
                <origin xyz=" 0 0 0" rpy="0 0 0" />
                <geometry>
                    <cylinder length="${base_length}" radius="${base_radius}"/>
                </geometry>
            </collision>   
            <cylinder_inertial_matrix  m="${base_mass}" r="${base_radius}" h="${base_length}" />
        </link>

        <gazebo reference="base_link">
            <material>Gazebo/Blue</material>
        </gazebo>

        <wheel prefix="left"  reflect="-1"/>
        <wheel prefix="right" reflect="1"/>

        <caster prefix="front" reflect="-1"/>
        <caster prefix="back"  reflect="1"/>

        <!-- controller -->
        <gazebo>
            <plugin name="differential_drive_controller" 
                    filename="libgazebo_ros_diff_drive.so">
                <rosDebugLevel>Debug</rosDebugLevel>
                <publishWheelTF>true</publishWheelTF>
                <robotNamespace>/</robotNamespace>
                <publishTf>1</publishTf>
                <publishWheelJointState>true</publishWheelJointState>
                <alwaysOn>true</alwaysOn>
                <updateRate>100.0</updateRate>
                <legacyMode>true</legacyMode>
                <leftJoint>left_wheel_joint</leftJoint>
                <rightJoint>right_wheel_joint</rightJoint>
                <wheelSeparation>${wheel_joint_y*2}</wheelSeparation>
                <wheelDiameter>${2*wheel_radius}</wheelDiameter>
                <broadcastTF>1</broadcastTF>
                <wheelTorque>30</wheelTorque>
                <wheelAcceleration>1.8</wheelAcceleration>
                <commandTopic>cmd_vel</commandTopic>
                <odometryFrame>odom</odometryFrame> 
                <odometryTopic>odom</odometryTopic> 
                <robotBaseFrame>base_footprint</robotBaseFrame>
            </plugin>
        </gazebo> 
    </xacro:macro>

</robot>

4.2.2 创建仿真环境
# view_mbot_gazebo_empty_world.launch文件内容

<launch>

    <!-- 设置launch文件的参数 -->
    <arg name="paused" default="false"/>
    <arg name="use_sim_time" default="true"/>
    <arg name="gui" default="true"/>
    <arg name="headless" default="false"/>
    <arg name="debug" default="false"/>

    <!-- 运行gazebo仿真环境 -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="debug" value="$(arg debug)" />
        <arg name="gui" value="$(arg gui)" />
        <arg name="paused" value="$(arg paused)"/>
        <arg name="use_sim_time" value="$(arg use_sim_time)"/>
        <arg name="headless" value="$(arg headless)"/>
    </include>

    <!-- 加载机器人模型描述参数 -->
    <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find mbot_description)/urdf/xacro/gazebo/mbot_gazebo.xacro'" /> 

    <!-- 运行joint_state_publisher节点,发布机器人的关节状态  -->
    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node> 

    <!-- 运行robot_state_publisher节点,发布tf  -->
    <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"  output="screen" >
        <param name="publish_frequency" type="double" value="50.0" />
    </node>

    <!-- 在gazebo中加载机器人模型-->
    <node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen"
          args="-urdf -model mrobot -param robot_description"/> 

</launch>

# 1.启动空环境下的.launch文件
roslaunch mbot_gazebo view_mbot_gazebo_empty_world.launch 

# 2.启动键盘控制节点
roslaunch mbot_teleop mbot_teleop.launch

# 3.添加环境模型
# 3.1 直接添加,把模型保存到~/.gazebo/models/下
cd ~/.gazebo/models/
git clone https://github.com/osrf/gazebo_models.git

# 添加好模型后,保存为.world文件

# 3.2 使用Buiding Editor,在gazebo的edit下
# 4.把仿真模型路径写入.launch文件,即可加载

效果如下图:

6

7

8

4.3 传感器仿真
4.3.1 摄像头仿真
  • < s e n s o r {\rm sensor} sensor>标签:描述传感器;

    • t y p e {\rm type} type:传感器类型, c a m e r a {\rm camera} camera
    • n a m e {\rm name} name:摄像头命名,自由设置;
  • < c a m e r a {\rm camera} camera>标签:描述摄像头参数;

    • 分辨率、编码格式、图像范围、噪音参数等;
  • < p l u g i n {\rm plugin} plugin>标签:加载摄像头仿真插件 l i b g a z e b o _ r o s _ c a m e r a . s o {\rm libgazebo\_ros\_camera.so} libgazebo_ros_camera.so

    • 设置插件的命名空间、发布图像的话题、参考坐标系等;
  • 摄像头仿真的 . x a c r o {\rm .xacro} .xacro文件实例

    # camera_gazebo.xacro文件内容
    
    <?xml version="1.0"?>
    <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="camera">
    
        <xacro:macro name="usb_camera" params="prefix:=camera">
            <!-- Create laser reference frame -->
            <link name="${prefix}_link">
                <inertial>
                    <mass value="0.1" />
                    <origin xyz="0 0 0" />
                    <inertia ixx="0.01" ixy="0.0" ixz="0.0"
                             iyy="0.01" iyz="0.0"
                             izz="0.01" />
                </inertial>
    
                <visual>
                    <origin xyz=" 0 0 0 " rpy="0 0 0" />
                    <geometry>
                        <box size="0.01 0.04 0.04" />
                    </geometry>
                    <material name="black"/>
                </visual>
    
                <collision>
                    <origin xyz="0.0 0.0 0.0" rpy="0 0 0" />
                    <geometry>
                        <box size="0.01 0.04 0.04" />
                    </geometry>
                </collision>
            </link>
            <gazebo reference="${prefix}_link">
                <material>Gazebo/Black</material>
            </gazebo>
    
            <gazebo reference="${prefix}_link">
                <sensor type="camera" name="camera_node">
                    <update_rate>30.0</update_rate>
                    <camera name="head">
                        <horizontal_fov>1.3962634</horizontal_fov>
                        <image>
                            <width>1280</width>
                            <height>720</height>
                            <format>R8G8B8</format>
                        </image>
                        <clip>
                            <near>0.02</near>
                            <far>300</far>
                        </clip>
                        <noise>
                            <type>gaussian</type>
                            <mean>0.0</mean>
                            <stddev>0.007</stddev>
                        </noise>
                    </camera>
                    <plugin name="gazebo_camera" filename="libgazebo_ros_camera.so">
                        <alwaysOn>true</alwaysOn>
                        <updateRate>0.0</updateRate>
                        <cameraName>/camera</cameraName>
                        <imageTopicName>image_raw</imageTopicName>
                        <cameraInfoTopicName>camera_info</cameraInfoTopicName>
                        <frameName>camera_link</frameName>
                        <hackBaseline>0.07</hackBaseline>
                        <distortionK1>0.0</distortionK1>
                        <distortionK2>0.0</distortionK2>
                        <distortionK3>0.0</distortionK3>
                        <distortionT1>0.0</distortionT1>
                        <distortionT2>0.0</distortionT2>
                    </plugin>
                </sensor>
            </gazebo>
    
        </xacro:macro>
    </robot>
    
    
# 1.在~/willard_ws/src/mbot_description/urdf/xacro/sensors/下新建camera_gazebo.xacro文件,内容见上一代码块
touch camera_gazebo.xacro

# 2.启动仿真环境
# view_mbot_with_camera_gazebo.launch内容见下一代码块
roslaunch mbot_gazebo view_mbot_with_camera_gazebo.launch

# 3.查看图像
rqt_image_view

# 4.启动键盘控制机器人移动
roslaunch mbot_teleop mbot_teleop.launch

# view_mbot_with_camera_gazebo.launch文件内容

<launch>

    <!-- 设置launch文件的参数 -->
    <arg name="world_name" value="$(find mbot_gazebo)/worlds/playground.world"/>
    <arg name="paused" default="false"/>
    <arg name="use_sim_time" default="true"/>
    <arg name="gui" default="true"/>
    <arg name="headless" default="false"/>
    <arg name="debug" default="false"/>

    <!-- 运行gazebo仿真环境 -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(arg world_name)" />
        <arg name="debug" value="$(arg debug)" />
        <arg name="gui" value="$(arg gui)" />
        <arg name="paused" value="$(arg paused)"/>
        <arg name="use_sim_time" value="$(arg use_sim_time)"/>
        <arg name="headless" value="$(arg headless)"/>
    </include>

    <!-- 加载机器人模型描述参数 -->
    <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find mbot_description)/urdf/xacro/gazebo/mbot_with_camera_gazebo.xacro'" /> 

    <!-- 运行joint_state_publisher节点,发布机器人的关节状态  -->
    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node> 

    <!-- 运行robot_state_publisher节点,发布tf  -->
    <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"  output="screen" >
        <param name="publish_frequency" type="double" value="50.0" />
    </node>

    <!-- 在gazebo中加载机器人模型-->
    <node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen"
          args="-urdf -model mrobot -param robot_description"/> 

</launch>

9

4.3.2 RGB-D摄像头(kinect)仿真
# 1.在~/willard_ws/src/mbot_description/urdf/xacro/sensors/下新建kinect_gazebo.xacro文件,内容见下一代码块
touch kinect_gazebo.xacro

# 2.启动仿真环境
# view_mbot_with_kinect_gazebo.launch内容见下一代码块
roslaunch mbot_gazebo view_mbot_with_kinect_gazebo.launch

# 3.查看图像
rosrun rviz rviz

# 4.启动键盘控制机器人移动
roslaunch mbot_teleop mbot_teleop.launch

# kinect_gazebo.xacro文件内容

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

    <xacro:macro name="kinect_camera" params="prefix:=camera">
        <!-- Create kinect reference frame -->
        <!-- Add mesh for kinect -->
        <link name="${prefix}_link">
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <visual>
                <origin xyz="0 0 0" rpy="0 0 ${M_PI/2}"/>
                <geometry>
                    <mesh filename="package://mbot_description/meshes/kinect.dae" />
                </geometry>
            </visual>
            <collision>
                <geometry>
                    <box size="0.07 0.3 0.09"/>
                </geometry>
            </collision>
        </link>

        <joint name="${prefix}_optical_joint" type="fixed">
            <origin xyz="0 0 0" rpy="-1.5708 0 -1.5708"/>
            <parent link="${prefix}_link"/>
            <child link="${prefix}_frame_optical"/>
        </joint>

        <link name="${prefix}_frame_optical"/>

        <gazebo reference="${prefix}_link">
            <sensor type="depth" name="${prefix}">
                <always_on>true</always_on>
                <update_rate>20.0</update_rate>
                <camera>
                    <horizontal_fov>${60.0*M_PI/180.0}</horizontal_fov>
                    <image>
                        <format>R8G8B8</format>
                        <width>640</width>
                        <height>480</height>
                    </image>
                    <clip>
                        <near>0.05</near>
                        <far>8.0</far>
                    </clip>
                </camera>
                <plugin name="kinect_${prefix}_controller" filename="libgazebo_ros_openni_kinect.so">
                    <cameraName>${prefix}</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>${prefix}_frame_optical</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>

    </xacro:macro>
</robot>

# view_mbot_with_kinect_gazebo.launch文件内容

<launch>

    <!-- 设置launch文件的参数 -->
    <arg name="world_name" value="$(find mbot_gazebo)/worlds/playground.world"/>
    <arg name="paused" default="false"/>
    <arg name="use_sim_time" default="true"/>
    <arg name="gui" default="true"/>
    <arg name="headless" default="false"/>
    <arg name="debug" default="false"/>

    <!-- 运行gazebo仿真环境 -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(arg world_name)" />
        <arg name="debug" value="$(arg debug)" />
        <arg name="gui" value="$(arg gui)" />
        <arg name="paused" value="$(arg paused)"/>
        <arg name="use_sim_time" value="$(arg use_sim_time)"/>
        <arg name="headless" value="$(arg headless)"/>
    </include>

    <!-- 加载机器人模型描述参数 -->
    <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find mbot_description)/urdf/xacro/gazebo/mbot_with_kinect_gazebo.xacro'" /> 

    <!-- 运行joint_state_publisher节点,发布机器人的关节状态  -->
    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node> 

    <!-- 运行robot_state_publisher节点,发布tf  -->
    <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"  output="screen" >
        <param name="publish_frequency" type="double" value="50.0" />
    </node>

    <!-- 在gazebo中加载机器人模型-->
    <node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen"
          args="-urdf -model mrobot -param robot_description"/> 

</launch>

仿真效果图:

10

4.3.3 激光雷达仿真
# 1.在~/willard_ws/src/mbot_description/urdf/xacro/sensors/下新建lidar_gazebo.xacro文件,内容见下一代码块
touch lidar_gazebo.xacro

# 2.启动仿真环境
# view_mbot_with_laser_gazebo.launch内容见下一代码块
roslaunch mbot_gazebo view_mbot_with_laser_gazebo.launch

# 3.查看图像
rosrun rviz rviz

# 4.启动键盘控制机器人移动
roslaunch mbot_teleop mbot_teleop.launch

# lidar_gazebo.xacro文件内容

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

    <xacro:macro name="rplidar" params="prefix:=laser">
        <!-- Create laser reference frame -->
        <link name="${prefix}_link">
            <inertial>
                <mass value="0.1" />
                <origin xyz="0 0 0" />
                <inertia ixx="0.01" ixy="0.0" ixz="0.0"
                         iyy="0.01" iyz="0.0"
                         izz="0.01" />
            </inertial>

            <visual>
                <origin xyz=" 0 0 0 " rpy="0 0 0" />
                <geometry>
                    <cylinder length="0.05" radius="0.05"/>
                </geometry>
                <material name="black"/>
            </visual>

            <collision>
                <origin xyz="0.0 0.0 0.0" rpy="0 0 0" />
                <geometry>
                    <cylinder length="0.06" radius="0.05"/>
                </geometry>
            </collision>
        </link>
        <gazebo reference="${prefix}_link">
            <material>Gazebo/Black</material>
        </gazebo>

        <gazebo reference="${prefix}_link">
            <sensor type="ray" name="rplidar">
                <pose>0 0 0 0 0 0</pose>
                <visualize>false</visualize>
                <update_rate>5.5</update_rate>
                <ray>
                    <scan>
                      <horizontal>
                        <samples>360</samples>
                        <resolution>1</resolution>
                        <min_angle>-3</min_angle>
                        <max_angle>3</max_angle>
                      </horizontal>
                    </scan>
                    <range>
                      <min>0.10</min>
                      <max>6.0</max>
                      <resolution>0.01</resolution>
                    </range>
                    <noise>
                      <type>gaussian</type>
                      <mean>0.0</mean>
                      <stddev>0.01</stddev>
                    </noise>
                </ray>
                <plugin name="gazebo_rplidar" filename="libgazebo_ros_laser.so">
                    <topicName>/scan</topicName>
                    <frameName>laser_link</frameName>
                </plugin>
            </sensor>
        </gazebo>

    </xacro:macro>
</robot>

仿真效果图:

11

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333263.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

打造安全可信的通信服务,阿里云云通信发布《短信服务安全白皮书》

随着数字化经济的发展&#xff0c;信息保护和数据安全成为企业、个人关注的焦点。近日&#xff0c;阿里云云通信发布《短信服务安全白皮书》&#xff0c;该白皮书包含安全责任共担、安全合规、安全架构三大板块&#xff0c;呈现了阿里云云通信在信息安全保护方面的技术能力、安…

【知识梳理】Go语言核心编程

基础知识 Go语言就是为了解决编程语言对并发支持不友好、编译速度慢、编程复杂这三个问题而诞生的 特点: Go语言选择组合思想,抛弃继承关系通过接口组合,自由组合成新接口,用接口实现层与层之间的解耦语言特性对比: package mainimport "fmt"func main() {fmt…

防灾必看,边滑坡安全预警解决方案

一、行业背景在我国大部分地区经常会有雨季发生&#xff0c;大量的雨水渗透到了土壤内部&#xff0c;长时间饱含雨水的土壤会变得很重而且还会减少与下方岩石之间的摩擦力&#xff0c;顺着山坡这个滑梯滑下去&#xff0c;造成崩塌、滑坡、泥石流等地质灾害。地质灾害每年都是有…

ccs导入工程失败的处理方法

文章目录当导入CCS新工程时出现下述错误怎么办&#xff1f;方法一 从TI官网下载安装包进行安装&#xff0c;下载链接&#xff1a;软件下载完成 安装路径为上面的文件夹点击安装完成后&#xff0c;导入安装路径&#xff0c;并点击Refresh按钮&#xff0c;依据路径进行更新&#…

电磁隔离放大器-模拟信号4-20mA/0-±10mA/0-±10V转0-75mV/0-2.5V/0-20mA信号转换模块

概述&#xff1a;导轨安装DIN11 IPO EM系列模拟信号隔离放大器是一种将输入信号隔离放大、转换成按比例输出的直流信号混合集成电路。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等需要电量隔离测控的行业。该模块内部嵌入了一个高效微功率的电源&#xff0c;…

10条终身受益的Salesforce职业发展建议!

Salesforce这个千亿美金巨兽&#xff0c;在全球范围内有42,000多名员工。作为一家发展迅速的科技公司&#xff0c;一直在招聘各种角色&#xff0c;包括销售、营销、工程师和管理人员等。 据IDC估计&#xff0c;从2016年到2020年&#xff0c;该生态系统创造了190万个工作岗位。…

解读 Java 云原生实践中的内存问题

作者&#xff1a;风敬&#xff08;谢文欣&#xff09; Java 凭借着自身活跃的开源社区和完善的生态优势&#xff0c;在过去的二十几年一直是最受欢迎的编程语言之一。步入云原生时代&#xff0c;蓬勃发展的云原生技术释放云计算红利&#xff0c;推动业务进行云原生化改造&…

电子科技大学人工智能期末复习笔记(四):概率与贝叶斯网络

目录 前言 概率 概率公式 贝叶斯公式 链式条件概率 例题 1. 求联合概率分布/边缘概率分布/条件概率分布 2. 灵活运用贝叶斯公式 概率总结 贝叶斯网络 判断独立性 两个事件独立的判断 条件独立性的判断 假设条件独立的链式法则 ⚠Active / Inactive Paths 判断独…

每个前端都应该掌握的7个代码优化的小技巧

本文将介绍7种JavaScript的优化技巧&#xff0c;这些技巧可以帮助你更好的写出简洁优雅的代码。 1. 字符串的自动匹配&#xff08;Array.includes&#xff09; 在写代码时我们经常会遇到这样的需求&#xff0c;我们需要检查某个字符串是否是符合我们的规定的字符串之一。最常…

MySQL进阶篇之锁(lock)

05、锁 5.1、概述 1、介绍 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;除传统的计算资源&#xff08;CPU、RAM、I/O&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据…

[DiceCTF 2023] rRabin

一点点学习别人的WP&#xff0c;这回看到一个大姥(r3kapig)的帖子&#xff0c;DiceCTF第二名&#xff0c;不过有好多东西一时还理解不了&#xff0c;得慢慢来。题目这个题有3个功能&#xff1a;rsa加密功能&#xff0c;p,q,N未知&#xff0c;e17低加密指数解密&#xff0c;不过…

JAVA的垃圾收集器与内存分配策略【一篇文章直接看懂】

内存动态分配和垃圾收集技术是JAVA和C之间最大的区别之一 垃圾收集&#xff08;Garbage Collection&#xff0c;GC&#xff09;只办三件事&#xff1a; 哪些内存需要回收什么时候回收如何回收 对于对象回收的方法 引用计数法&#xff1a; 每处引用时1&#xff0c;引用失效…

软件测试标准流程

软件测试的基本流程大概要经历四个阶段&#xff0c;分别是制定测试计划、测试需求分析、测试用例设计与编写以及测试用例评审。因此软件测试的工作内容&#xff0c;远远没有许多人想象的只是找出bug那么简单。准确的说&#xff0c;从一个项目立项以后&#xff0c;软件测试从业者…

第一章 认识Python

本章目录 一、初识Python 二、Python环境安装 三、Python代码的执行 四、Python集成开发环境 五、Python2.x与Python3.x的区别 六、本章小结 Python代码的编辑和运行方式主要分为两种&#xff1a;交互模式和脚本模式。 在交互模式下&#xff0c; 用户输入Python代码并按…

非常棒的13款3DMax渲染器插件推荐给大家

3Ds Max 可能是具有最多可与其集成的外部渲染引擎的 3D 软件包。 今天我们将看看 13 个最好的 3Ds max 渲染插件&#xff0c;我们将从以下列表开始&#xff1a; 13- Radeon ProRender ProRender 的正式名称为 FireRender&#xff0c;是 AMD 的开源路径追踪器。这个 3ds Max …

Redis的缓存雪崩、击穿、穿透和解决方案

2.5 缓存穿透问题的解决思路 缓存穿透 &#xff1a;缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库。 常见的解决方案有两种&#xff1a; 缓存空对象 优点&#xff1a;实现简单&#xff0c;维护…

程序员不得不知道的 API 接口常识

说实话&#xff0c;我非常希望自己能早点看到本篇文章&#xff0c;大学那个时候懵懵懂懂&#xff0c;跟着网上的免费教程做了一个购物商城就屁颠屁颠往简历上写。 至今我仍清晰地记得&#xff0c;那个电商教程是怎么定义接口的&#xff1a; 管它是增加、修改、删除、带参查询…

CentOS7.6 zabix5.0-0 —agent2监控Mysql数据库(linux)

Mysql数据库安装步骤链接&#xff1a;https://bbs.huaweicloud.com/blogs/245624 &#xff08;已安装数据库此步骤可省略~&#xff01;&#xff01;&#xff09; 至少需要两台虚拟机进行试验 一台服务端&#xff08;监控端&#xff09;jk 一台客户端&#xff08;被监控端&…

【(C语言)数据结构奋斗100天】二叉树(上)

【(C语言)数据结构奋斗100天】二叉树&#xff08;上&#xff09; &#x1f3e0;个人主页&#xff1a;泡泡牛奶 &#x1f335;系列专栏&#xff1a;数据结构奋斗100天 本期所介绍的是二叉树&#xff0c;那么什么是二叉树呢&#xff1f;在知道答案之前&#xff0c;请大家思考一下…

Window 10 OpenCV 打开罗技(Logitech)摄像头速度慢问题解决

采用最新版OpenCV 4.7.0 摄像头对罗技摄像头进行视频图像抓取时&#xff0c;发现存在打开摄像头问题。 测试环境如下&#xff1a; 系统Windows 10 专业版CPUIntel i7-7700K 4.20GHz 摄像头型号罗技Logitech C930c 网络摄像头OpenCV版本4.7.0语言C 测试结果表明&#xff1a; …