Clase 08 - Taller de resolución

URDF y XACRO

URDF

Etiqueta <robot>..<\robot>

  • Etiqueta raíz (todo el contenido se encuentra dentro)
<?xml version="1.0"?>

<robot name="mi_robot">
    ...
    <!-- Contenido URDF -->
    ... 
</robot>

Etiqueta <joint> .. </joint>

Joint
  • 2 atributos: el nombre y tipo
  • 2 elementos requeridos: link padre e hijo
  • Tipos:
    • Fija (fixed)
    <joint name="parteA_joint" type="fixed">
      <parent link="padre_link"/>
      <child link="parteA_link"/>
      <origin xyz="[pos_x] [pos_y] [pos_z]"
          rpy="[roll] [pitch] [yaw]"/>
    </joint>
    • Continua (continuous)
    <joint name="parteA_joint" type="revolute">
      <parent link="padre_link"/>
      <child link="parteA_link"/>
      <origin xyz="[pos_x] [pos_y] [pos_z]"
          rpy="[roll] [pitch] [yaw]"/>
      <axis xyz="[x] [y] [z]"/>
    </joint>
    • Revolución (revolute)
    <joint name="parteA_joint" type="revolute">
      <parent link="padre_link"/>
      <child link="parteA_link"/>
      <origin xyz="[pos_x] [pos_y] [pos_z]"
          rpy="[roll] [pitch] [yaw]"/>
      <axis xyz="[x] [y] [z]"/>
      <limit lower="[min_rad]" upper="[max_rad]"
          velocity="[rad_por_seg]"
          effort="[effort]" />
    </joint>

XACRO

Agregar al tag robot del URDF xmlns:xacro="http://www.ros.org/wiki/xacro":

<robot name="mi_robot" xmlns:xacro="http://www.ros.org/wiki/xacro" >
    ...
    <!-- Contenido -->
    ... 
</robot>

Inclusión de archivos

  • Archivo principal: extensión ‘.urdf.xacro’ y contiene el tag robot con nombre
  • Archivos a incluir: extensión ‘.xacro’ y solo contienen el tag robot
  • Para incluir:
    <xacro:include filename="[nombre_archivo]" />

Parametrización de atributos

  • Propiedades xacro:property: Nombre y valor
    <xacro:property name="diametro" value="2.1" />
  • Operaciones matemáticas y acceso a variables: ${..}
    <geometry type="cylinder" radius="${diametro / 2}" length="${nombre_variable}" />
  • Argumentos xacro:args: Nombre y valor por defecto
    <xacro:arg name="[nombre_argumento]" default="[valor_defecto]"/>

Luego podemos ejecutar el comando XACRO con el valor del argumento nombre_argumento:=[valor]

  • Buscar paquetes $(find ..):
    <xacro:include filename="$(find [nombre_paquete])/[nombre_archivo].xacro" />

Bloques condicionales

  • Etiqueta xacro:if para true y xacro:unless para false
<xacro:if value="[expresion]">
    <!-- Si la expresión es verdadera: 'true' o 1 -->
</xacro:if>
<xacro:unless value="[expresion]">
    <!-- Si la expresión es falsa: 'false' o 0  -->
</xacro:unless>

Macros

  • Definir macro xacro:macro: Nombre y parámetros a recibir
<xacro:macro name="[nombre_macro]" params="[param1] [param2]:=[valor_defecto]">
    <!-- Codigo del macro: ejemplo con parámetros -->
    <link name="${param1}">
        <visual>
            <geometry>
                <sphere radius="${param2}" />
            </geometry>
        </visual>
    </link>
</xacro:macro>
  • Aplicar o ejecutar macro xacro:[nombre_macro] y los parámetros definidos:
<xacro:nombre_macro param1="[valor_param1]" param2="[valor_param2]" /> 
  • Si ejecutamos el macro con los valores parteA_link y 1.0, la salida será:
...
    <link name="parteA_link">
        <visual>
            <geometry>
                <sphere radius="1.0" />
            </geometry>
        </visual>
    </link>
...

Compilación del URDF

  • Desde consola

      $ xacro [ubicacion_del_archivo/nombre_archivo.xacro.urdf]
  • Desde launch

    • Importar las librerías
    from launch.substitutions import Command, PathJoinSubstitution
    from launch_ros.substitutions import FindPackageShare
    • Ubicar el archivo y procesarlo
      # Ubicación del paquete y del archivo URDF
      urdf_path = PathJoinSubstitution(
          [FindPackageShare("[nombre_paquete]"),  "urdf", "[nombre_archivo].urdf.xacro"]
      )
    
      # Procesar archivo URDF
      urdf = Command(['xacro ', urdf_path])

Adaptación del paquete

  • Se agrega la carpeta urdf para los archivos de descripción
Ejemplo de estructura
📂 paquete_description
    📁 paquete_description
    📂 launch
        📄 description.launch.py
        ...
    📂 urdf
        📄 description.urdf.xacro
        📄 materials.xacro
        📄 my_macro.xacro
        📄 sim_sensor.xacro
        ...
    📄 package.xml
    📄 setup.py
    ...
  • Configuración de setup.py
setup.py
  # ... Otros parámetros
  data_files=[
    # ... Otros archivos
    # Incluir todos los archivos de la carpeta launch
    (os.path.join('share', package_name, 'launch'), glob('launch/*'))
    # Incluir todos los archivos de la carpeta urdf
    (os.path.join('share', package_name, 'urdf'), glob('urdf/*'))
    # Incluir todos los archivos de la carpeta meshes
    (os.path.join('share', package_name, 'meshes'), glob('meshes/*'))
  ],

Robot state publisher y joint publishers

robot_state_publisher

  • Ejecutar desde consola
    $ ros2 run robot_state_publisher robot_state_publisher
                --ros-args -p robot_description:='<robot_description>'
  • Cargar desde launch
    Node(
        package = 'robot_state_publisher',
        executable = 'robot_state_publisher',
        parameters=[{
            'robot_description': '<robot_description>',
        }]
    )

joint_state_publisher_gui

  • Ejecutar desde consola
    $ ros2 run joint_state_publisher_gui joint_state_publisher_gui
  • Cargar desde launch:
    Node(
        package = 'joint_state_publisher_gui',
        executable = 'joint_state_publisher_gui',
        output = 'screen',
    )

Resolución ejercicios 1 y 2

Crear un paquete de ROS llamado (*)_description para albergar el robot description siguiendo la estructura vista en clases. Crear un archivo de definición del robot en formato XACRO respetando la geometría representada en las vistas del anexo y cumpliendo con los siguientes requerimientos:

  • Debe contener al menos un base_link asignado al chasis del robot y un link y un joint por cada rueda
  • Cada link deberá tener definida la geometría visual y de colisión, según la tabla correspondiente del anexo
  • Debe estar parametrizado al menos el radio de las ruedas de tracción y la separación de las mismas
  • En caso de poder reutilizar bloques, hacer uso de macros
  • Utilice el macro motor importando el archivo motor.xacro para ubicar el motor izquierdo y derecho. El macro recibe 3 parámetros:
    • prefix (String): para diferenciar el link con un prefijo
    • chassis_width (Double): ancho del chasis
    • reflect (Bool): No reflejar (False) o sí reflejar (True). La orientación original es hacia la izquierda

En el mismo paquete, crear un archivo launch de nombre description.launch.py, en el cuál se deberá procesar el archivo XACRO con la descripción del robot y se deberá publicar la misma a través del paquete robot_state_publisher. El launch deberá recibir, a través de un parámetro de tipo bool llamado testing, la condición para ejecutar o no el paquete joint_state_publisher_gui y RViz.

Este archivo será útil para probar el archivo del ejercicio anterior, por lo que se recomienda realizarlos en paralelo