ROS Efficient Advanced Capítulo 2 - Use o robô com rodas diferenciais como um exemplo para aprender modelagem de robô URDF e otimização xacro

1 recurso

Este artigo é o segundo capítulo do ROS Efficient Advanced. Usamos a linguagem URDF (formato xml) para fazer um modelo diferencial de robô com rodas, e usamos a versão aprimorada do URDF xacro para realizar otimização secundária no arquivo do modelo do robô.
Robô de roda diferencial: O chassi diferencial de duas rodas consiste em duas rodas motorizadas localizadas nos lados esquerdo e direito do chassi. As duas rodas controlam a velocidade independentemente e o controle de direção do chassi é realizado fornecendo velocidades diferentes. Geralmente, será equipado com uma ou duas rodas universais para suporte auxiliar.
Nesta modelagem, nenhum algoritmo é introduzido, apenas a aparência do modelo do robô é feita, portanto, apenas o rivz é usado para exibição visual.
Referências para este artigo:
(0) Modelo de cinemática de robô diferencial de duas rodas
(1) Capítulo 5 e Capítulo 6 da "Prática de desenvolvimento de robôs ROS" Hu Chunxu (
2) Resumo da exploração ROS: Interpretação de URDF
(3) Resumo da exploração ROS: Como para começar do zero Criar um modelo de robô (braço do robô)
(4) ROS Efficient Advanced Capítulo 1 – rviz de ROS Advanced Components

2 texto

2.1 Definição e composição de robôs

(1) Definição de robô: Um robô é uma máquina automatizada. A diferença é que esta máquina possui algumas habilidades inteligentes semelhantes aos humanos ou criaturas, como percepção, planejamento, ação e coordenação. É uma máquina automatizada avançada para flexibilidade.
Atualmente, os carros autônomos também são considerados um tipo de robô.
(2) Composição dos robôs: Os robôs geralmente são divididos em quatro partes, ou seja, atuadores, sistemas de acionamento, sistemas de detecção e sistemas de controle.
Tomando carros autônomos como exemplo, o atuador é o acelerador, direção e freio; o sistema de direção é o motor; o sistema de detecção é vários sensores: lidar, radar, câmera, uss, imu, GNSS; o sistema de controle é o sistema de algoritmo de condução inteligente: percepção, posicionamento, planejamento e controle.
(3) As malhas de controle das quatro partes principais do robô são aproximadamente as mostradas na figura:
insira a descrição da imagem aqui

2.2 Rotina de modelagem URDF

(1) URDF: Unified Robot Description Format, um formato de arquivo de descrição de robô unificado. os arquivos urdf usam o formato xml.
(2) Usando urdf para descrever o robô, a rotina é a seguinte: cada robô é composto por vários links (bielas) e juntas (articulações). O elo e a junta aqui são muito amplos e as formas não são necessariamente hastes e eixos. Por exemplo, uma mesa, tampo de mesa e pernas são todos elos e as juntas são juntas fixas.

<?xml version="1.0" ?>
<robot name="name of robot">
	<link> ... </link>
	<joint> ... </joint>
	...
</robot>

insira a descrição da imagem aqui
(3) link: Descreva a aparência e as propriedades físicas de uma parte rígida do corpo do robô. Aparência inclui: tamanho, cor, forma. As propriedades físicas incluem: matriz de inércia (matriz inercial) e parâmetros de colisão (propriedades de colisão). Na modelagem de robôs, cada link é um sistema de coordenadas.
A seguir está a modelagem do chassi do robô de roda diferencial, que geralmente é chamado de base.

  <link name="base_link">
  	// visual 标签就是外观
    <visual>
      // base_link本身是个坐标系,这也是差速轮式机器人各组成部分的根坐标系,一般会把他的坐标原点设置在rviz的中心处
      // origin表示底盘在其base_link坐标系下的原始位置和旋转状态
      // xyz表示底盘质心在base_link坐标系的偏移位置,rpy(roll,pitch,yaw)是底盘绕base_link的x,y,z三个轴的旋转值
      <origin xyz="0 0 0" rpy="0 0 0"/>
      // geometry是物体几何外形
      <geometry>
      	// 这里的底盘,用圆柱体表示,length值为高度,radius是半径值
        <cylinder length="0.16" radius="0.2"/>
      </geometry>
      // material是材料,这里指定底盘颜色为红色,rgba是三色+透明度表示法,三色的范围是0~1,而不是0-255
      <material name="red">
        <color rgba="1 0 0 1"/>
      </material>
    </visual>
  </link>

Suplemento: Aqui fazemos apenas modelagem de aparência, portanto, não envolvemos a configuração de atributos físicos por enquanto Ao simular no gazebo no próximo capítulo, adicionaremos atributos físicos ao link na amostra.
(4) junta: Descreve a relação entre dois links, incluindo atributos cinemáticos e dinâmicos.Aqui focamos apenas nos atributos cinemáticos. Normalmente, a relação entre dois links geralmente é dividida em seis tipos:

continuous:旋转关节,可以围绕单轴360度无限旋转,比如轮子的轴
revolute:旋转关节,但是有旋转角度的范围限制,比如钟摆
prismatic:滑动关节,也叫活塞关节,沿某一轴线移动的关节,有位置限制,强调一维,比如打气筒
planar:平面关节,允许在平面正交方向上平移或旋转,强调平面,比如抽屉内外滑动
floating:浮动关节,允许进行平移和旋转运动,比如人体的肩关节
fixed:固定关节,比如桌子腿和桌面

A seguir, um exemplo de união entre a roda motriz e o chassi do robô de roda diferencial:

  // joint标签就是关节,type表示链接关系
  <joint name="left_wheel_joint" type="continuous">
    // origin表示轮子在base_link坐标系下的偏移和旋转
    <origin xyz="0 0.19 -0.05" rpy="0 0 0" />
    // 根link是底盘,子link是轮子
    <parent link="base_link" />
    <child link="left_wheel_link" />
    // axis描述的轮子相对于其自身坐标系的 y 轴旋转,=
    <axis xyz="0 1 0" />
  </joint>
  
  // 这是轮子link
  <link name="left_wheel_link">
    <visual>
      // 轮子相当于其x轴,旋转90度,也就是立起来
      <origin xyz="0 0 0" rpy="1.5707 0 0"/>
      <geometry>
        <cylinder length="0.06" radius="0.06"/>
      </geometry>
      <material name="white">
        <color rgba="1 1 1 0.9"/>
      </material>
    </visual>
  </link>

2.3 Use URDF para fazer um modelo de robô com rodas diferenciais

(1) Crie o pacote mbot_description e arquivos relacionados

cd ~/catkin_ws/src
catkin_create_pkg mbot_description urdf xacro

cd mbot_description 
mkdir -p config doc launch meshes urdf/sensor
touch launch/display_mbot_urdf.launch launch/display_mbot_xacro.launch
touch urdf/mbot_base.urdf urdf/mbot_base.xacro
touch urdf/sensor/camera.xacro urdf/sensor/kinect.xacro urdf/sensor/laser.xacro

(2) mbot_base.urdf: Este é o arquivo de modelagem mbot completo, incluindo o chassi, duas rodas motorizadas, duas rodas universais, uma câmera, um kinect (câmera de profundidade) e um lidar. Para a gramática específica, consulte a introdução na seção anterior, portanto não a repetirei aqui.

<?xml version="1.0" ?>
<robot name="mbot">

  <link name="base_link">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <cylinder length="0.16" radius="0.2"/>
      </geometry>
      <material name="red">
        <color rgba="1 0 0 1"/>
      </material>
    </visual>
  </link>

  <joint name="left_wheel_joint" type="continuous">
    <origin xyz="0 0.19 -0.05" rpy="0 0 0" />
    <parent link="base_link" />
    <child link="left_wheel_link" />
    <axis xyz="0 1 0" />
  </joint>

  <link name="left_wheel_link">
    <visual>
      <origin xyz="0 0 0" rpy="1.5707 0 0"/>
      <geometry>
        <cylinder length="0.06" radius="0.06"/>
      </geometry>
      <material name="white">
        <color rgba="1 1 1 0.9"/>
      </material>
    </visual>
  </link>

  <joint name="right_wheel_joint" type="continuous">
    <origin xyz="0 -0.19 -0.05" rpy="0 0 0" />
    <parent link="base_link" />
    <child link="right_wheel_link" />
    <axis xyz="0 1 0" />
  </joint>

  <link name="right_wheel_link">
    <visual>
      <origin xyz="0 0 0" rpy="1.5707 0 0"/>
      <geometry>
        <cylinder length="0.025" radius="0.06" />
      </geometry>
      <material name="white">
        <color rgba="1 1 1 0.9"/>
      </material>
    </visual>
  </link>

  <joint name="front_caster_joint" type="continuous">
    <origin xyz="0.18 0 -0.095" rpy="0 0 0" />
    <parent link="base_link"/>
    <child link="front_caster_link" />
    <axis xyz="0 1 0" />
  </joint>

  <link name="front_caster_link">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry>
        <sphere radius="0.015" />
      </geometry>
      <material name="white">
        <color rgba="1 1 1 0.9"/>
      </material>
    </visual>
  </link>

  <joint name="back_caster_joint" type="continuous">
    <origin xyz="-0.18 0 -0.095" rpy="0 0 0" />
    <parent link="base_link"/>
    <child link="back_caster_link" />
    <axis xyz="0 1 0" />
  </joint>

  <link name="back_caster_link">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry>
        <sphere radius="0.015" />
      </geometry>
      <material name="white">
        <color rgba="1 1 1 0.9"/>
      </material>
    </visual>
  </link>

  <joint name="camera_joint" type="fixed">
    <origin xyz="-0.17 0 0.1" rpy="0 0 0" />
    <parent link="base_link"/>
    <child link="camera_link" />    
  </joint>

  <link name="camera_link">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry>
        <box size="0.03 0.04 0.04" />
      </geometry>
      <material name="grey">
        <color rgba="0.5 0.5 0.5 1"/>
      </material>
    </visual>
  </link>

  <joint name="stage_joint" type="fixed">
    <origin xyz="0 0 0.14" rpy="0 0 0" />
    <parent link="base_link"/>
    <child link="stage_link" />    
  </joint>

  <link name="stage_link">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <cylinder length="0.12" radius="0.1"/>
      </geometry>
      <material name="red">
        <color rgba="1 0 0 1"/>
      </material>
    </visual>
  </link>

  <joint name="laser_joint" type="fixed">
    <origin xyz="0 0 0.085" rpy="0 0 0" />
    <parent link="stage_link"/>
    <child link="laser_link" />    
  </joint>

  <link name="laser_link">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry>
        <cylinder length="0.05" radius="0.05"/>
      </geometry>
      <material name="grey">
        <color rgba="0.5 0.5 0.5 1"/>
      </material>
    </visual>
  </link>

  <joint name="kinect_joint" type="fixed">
    <origin xyz="0.15 0 0.11" rpy="0 0 0" />
    <parent link="base_link"/>
    <child link="kinect_link" />    
  </joint>

  <link name="kinect_link">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 1.5708" />
      <geometry>
        // 使用三维软件导出的模型文件
        <mesh filename="package://mbot_description/meshes/kinect.dae" />
      </geometry>
    </visual>
  </link>
</robot>

(3)display_mbot_urdf.launch

<launch>
  // 设置ros的全局参数robot_description,指定机器人模型文件
  <param name="robot_description" textfile="$(find mbot_description)/urdf/mbot_base.urdf" />

	<!-- 设置GUI参数,显示关节控制插件 -->
	// 用这个可以控制机器人关节,但本文的demo没看到这个,有点遗憾
	<param name="use_gui" value="true"/>

	<!-- 运行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" />

	// robot_state_publisher结合joint_state_publisher可以实时把机器人各关节和各坐标系关系发布出来,让rviz显示。如果不设置,rviz无法完整加载机器人模型。
	// rviz显示后会生成配置文件,保存后再打开,就不用频繁设置了。
	<!-- 运行rviz可视化界面 -->
	<node name="rviz" pkg="rviz" type="rviz" args="-d $(find mbot_description)/config/mbot_urdf.rviz" required="true" />

</launch>

(4) Use a ferramenta de linha de comando urdf_to_graphiz para despejar o conteúdo do arquivo urdf na forma de uma árvore em formato pdf. Use isso para ler rapidamente o link e a junção de urdf, a figura a seguir é o diagrama de árvore de nós do exemplo acima.

cd ~/catkin_ws/
urdf_to_graphiz src/mbot_description/urdf/mbot_base.urdf

insira a descrição da imagem aqui

(5) Compilar e executar

cd ~/catkin_ws/
catkin_make --source src/mbot_description
source devel/setup.bash
roslaunch mbot_description display_mbot_urdf.launch

insira a descrição da imagem aqui
insira a descrição da imagem aqui

2.4 Usando xacro para otimizar o modelo de robô com rodas diferenciais

(1) A sintaxe urdf original é relativamente simples, resultando em arquivos de modelo de robô prolixo. Por exemplo, a escrita de duas rodas de força e duas rodas universais é muito repetitiva. O ROS propõe a sintaxe xacro para permitir que arquivos de modelo de robô sejam programáveis, como configuração de parâmetros, definição de funções de macro e chamada, e inclusão de arquivo. O seguinte é um exemplo de classificação:
configuração e chamada de parâmetros:

   // xacro:property设置参数
  <xacro:property name="M_PI" value="3.1415926" />
  // 引用参数用${}
  <origin xyz="0 0 0" rpy="${M_PI/2} 0 0"/>

Configure a função de macro e chame:

  // xacro:macro设置宏函数,名字是wheel,参数是prefix 和 reflect
  <xacro:macro name="wheel" params="prefix reflect">
    <joint name="${prefix}_wheel_joint" type="continuous">
      <origin xyz="${wheel_joint_x} ${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 length="${wheel_length}" radius="${wheel_radius}"/>
        </geometry>
        <material name="white" />
      </visual>
    </link>
  </xacro:macro>
  // 调用wheel宏函数
  <xacro:wheel prefix="left"  reflect="1"/>  
  <xacro:wheel prefix="right"  reflect="-1"/>  

arquivo contém

  // xacro:include是文件包含,camera.xacro里面定义了一个宏函数
  <xacro:include filename="$(find mbot_description)/urdf/sensor/camera.xacro" />
  // 调用camera.xacro里面的宏函数
  <xacro:usb_camera joint_x="${camera_joint_x}" joint_y="${camera_joint_y}" joint_z="${camera_joint_z}"/>  

(2) Os vários arquivos aqui são a reescrita do mbot_base.urdf acima, usando xacro, veja a explicação acima para a sintaxe específica.
mbot_base.xacro

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

  <xacro:property name="wheel_joint_x" value="0" />
  <xacro:property name="wheel_joint_y" value="0.19" />
  <xacro:property name="wheel_joint_z" value="0.05" />

  <xacro:property name="wheel_length" value="0.06" />
  <xacro:property name="wheel_radius" value="0.06" />

  <xacro:property name="caster_joint_x" value="0.18" />
  <xacro:property name="caster_joint_y" value="0" />
  <xacro:property name="caster_joint_z" value="0.095" />  

  <xacro:property name="caster_radius" value="0.015" />

  <xacro:property name="base_length" value="0.16" />
  <xacro:property name="base_radius" value="0.2" />

  <xacro:property name="stage_length" value="0.12" />
  <xacro:property name="stage_radius" value="0.1" />

  <xacro:property name="camera_joint_x" value="0.17" />
  <xacro:property name="camera_joint_y" value="0" />
  <xacro:property name="camera_joint_z" value="0.1" />  

  <xacro:property name="kinect_joint_x" value="0.15" />
  <xacro:property name="kinect_joint_y" value="0" />
  <xacro:property name="kinect_joint_z" value="0.11" />  

  <xacro:property name="laser_joint_x" value="0" />
  <xacro:property name="laser_joint_y" value="0" />
  <xacro:property name="laser_joint_z" value="0.085" />  

  <material name="white">
    <color rgba="1 1 1 0.9"/>
  </material>
  <material name="red">
    <color rgba="1 0 0 1"/>
  </material>

  <material name="grey">
    <color rgba="0.5 0.5 0.5 1"/>
  </material>

  <xacro:macro name="base_stage">
    <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="red" />
      </visual>
    </link>

    <joint name="stage_joint" type="fixed">
      <origin xyz="0 0 ${(base_length + stage_length)/2}" rpy="0 0 0" />
      <parent link="base_link"/>
      <child link="stage_link" />    
    </joint>

    <link name="stage_link">
      <visual>
        <origin xyz="0 0 0" rpy="0 0 0"/>
        <geometry>
          <cylinder length="${stage_length}" radius="${stage_radius}"/>
        </geometry>
        <material name="red" />
      </visual>
    </link>
  </xacro:macro>

  <xacro:macro name="wheel" params="prefix reflect">
    <joint name="${prefix}_wheel_joint" type="continuous">
      <origin xyz="${wheel_joint_x} ${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 length="${wheel_length}" radius="${wheel_radius}"/>
        </geometry>
        <material name="white" />
      </visual>
    </link>
  </xacro:macro>

  <xacro:macro name="caster" params="prefix reflect">
    <joint name="${prefix}_caster_joint" type="continuous">
      <origin xyz="${reflect*caster_joint_x} ${caster_joint_y} ${-caster_joint_z}" 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="white" />
      </visual>
    </link>
  </xacro:macro>

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

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

  <xacro:include filename="$(find mbot_description)/urdf/sensor/camera.xacro" />
  <xacro:usb_camera joint_x="${camera_joint_x}" joint_y="${camera_joint_y}" joint_z="${camera_joint_z}"/>  

  <xacro:include filename="$(find mbot_description)/urdf/sensor/kinect.xacro" />
  <xacro:kinect joint_x="${kinect_joint_x}" joint_y="${kinect_joint_y}" joint_z="${kinect_joint_z}"/>  

  <xacro:include filename="$(find mbot_description)/urdf/sensor/laser.xacro" />
  <xacro:laser joint_x="${laser_joint_x}" joint_y="${laser_joint_y}" joint_z="${laser_joint_z}"/>  

</robot>

camera.xacro

<?xml version="1.0" ?>
<robot name="mbot" xmlns:xacro="http://www.ros.org/wiki/xacro">
  <xacro:macro name="usb_camera" params="joint_x joint_y joint_z">
    <joint name="camera_joint" type="fixed">
      <origin xyz="${-joint_x} ${joint_y} ${joint_z}" rpy="0 0 0" />
      <parent link="base_link"/>
      <child link="camera_link" />    
    </joint>

    <link name="camera_link">
      <visual>
        <origin xyz="0 0 0" rpy="0 0 0" />
        <geometry>
          <box size="0.03 0.04 0.04" />
        </geometry>
        <material name="grey" />
      </visual>
    </link>
  </xacro:macro>
</robot>

kinect.xacro

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

  <xacro:macro name="kinect" params="joint_x joint_y joint_z">
    <joint name="kinect_joint" type="fixed">
      <origin xyz="${joint_x} ${joint_y} ${joint_z}" rpy="0 0 0" />
      <parent link="base_link"/>
      <child link="kinect_link" />    
    </joint>

    <link name="kinect_link">
      <visual>
        <origin xyz="0 0 0" rpy="0 0 1.5708" />
        <geometry>
          <mesh filename="package://mbot_description/meshes/kinect.dae" />
        </geometry>
      </visual>
    </link>
  </xacro:macro>

</robot>

laser.xacro

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

  <xacro:macro name="laser" params="joint_x joint_y joint_z">
    <joint name="laser_joint" type="fixed">
      <origin xyz="${joint_x} ${joint_y} ${joint_z}" rpy="0 0 0" />
      <parent link="stage_link"/>
      <child link="laser_link" />    
    </joint>

    <link name="laser_link">
      <visual>
        <origin xyz="0 0 0" rpy="0 0 0" />
        <geometry>
          <cylinder length="0.05" radius="0.05"/>
        </geometry>
        <material name="grey"/>
      </visual>
    </link>
  </xacro:macro>
</robot>

(3)display_mbot_xacro.launch

<launch>
	// 引入xacro的解释器,不然无法读取 .xacro文件
	<arg name="model" default="$(find xacro)/xacro '$(find mbot_description)/urdf/mbot_base.xacro'" />

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

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

	<!-- 运行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_xacro.rviz" required="true" />

</launch>

(4) O efeito de corrida é o seguinte, onde os eixos do sistema de coordenadas são mostrados
insira a descrição da imagem aqui
insira a descrição da imagem aqui

3 Resumo

O código deste artigo está hospedado no meu github: mbot_description

Acho que você gosta

Origin blog.csdn.net/cy1641395022/article/details/131830631
Recomendado
Clasificación