{"id":2595,"date":"2022-06-30T14:10:54","date_gmt":"2022-06-30T14:10:54","guid":{"rendered":"https:\/\/robotica-facil-con-ros2.es\/?p=2595"},"modified":"2022-09-09T22:07:29","modified_gmt":"2022-09-09T22:07:29","slug":"como-revisar-los-archivos-urdf","status":"publish","type":"post","link":"https:\/\/robotica-facil-con-ros2.es\/?p=2595","title":{"rendered":"C\u00f3mo revisar los archivos URDF"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"2595\" class=\"elementor elementor-2595\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-6c235fd elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"6c235fd\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-de129c4\" data-id=\"de129c4\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3802bf7 elementor-widget elementor-widget-text-editor\" data-id=\"3802bf7\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Cuando nuestro modelo es complicado puede ser bastante tedioso revisar el c\u00f3digo URDF en caso de que nos aparezca alg\u00fan tipo de error o cuando el comportamiento de las articulaciones no es el esperado.<\/p><p>En este art\u00edculo vamos a ver algunas herramientas que tenemos a nuestra disposici\u00f3n y que nos van a ayudar a identificar y resolver algunos de los problemas que nos pueden surgir con los archivos URDF.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b6ca396 elementor-widget elementor-widget-text-editor\" data-id=\"b6ca396\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<h4>Comprobaci\u00f3n de la sintaxis<\/h4><p>Podemos asegurar que el<span style=\"background-color: var(--ast-global-color-4); color: var(--ast-global-color-3); font-style: inherit; font-weight: inherit;\">\u00a0c\u00f3digo no tiene errores de sintaxis empleando las herramientas <\/span><span style=\"background-color: var(--ast-global-color-4); color: #0170b9;\"><i>check_urdf<\/i><\/span><span style=\"background-color: var(--ast-global-color-4); color: var(--ast-global-color-3); font-style: inherit; font-weight: inherit;\"> y <\/span><span style=\"background-color: var(--ast-global-color-4); color: #0170b9;\"><i>urdf_to_graphiz<\/i><\/span><span style=\"background-color: var(--ast-global-color-4); color: var(--ast-global-color-3); font-style: inherit; font-weight: inherit;\"> que se encuentran en el paquete debian\u00a0<\/span><span style=\"color: #36464e; font-family: 'Roboto Mono', SFMono-Regular, Consolas, Menlo, monospace; font-size: 14.96px; background-color: var(--ast-global-color-4);\"><i>liburdfdom-tools<\/i>.<\/span><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8fe9cbf elementor-widget elementor-widget-text-editor\" data-id=\"8fe9cbf\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Si no tenemos ya dicho paquete ejecutaremos desde el terminal el siguiente comando para instalarlo.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-308acc7 elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"308acc7\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-308acc7\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-tomorrow\"\n            data-dark-theme=\"mdp-theme-tomorrow\"\n        >\n            \n                <pre class=\"language-shell-session copy-to-clipboard\"data-previewers=\"\"><code>sudo apt install liburdfdom-tools<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_308acc7 = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_308acc7();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_308acc7 );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0ca990d elementor-widget elementor-widget-text-editor\" data-id=\"0ca990d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>En caso de que hayamos empleado el lenguaje de macros XACRO es necesario como paso previo generar el archivo con el c\u00f3digo URDF. Para ello ejecutamos el siguiente comando, donde hay que sustituir <i>xacro_file<\/i> por el archivo con el c\u00f3digo XACRO y <i>urdf_file<\/i> por el nombre que queramos dar al archivo de salida.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e4d90dd elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"e4d90dd\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-e4d90dd\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-tomorrow\"\n            data-dark-theme=\"mdp-theme-tomorrow\"\n        >\n            \n                <pre class=\"language-shell-session copy-to-clipboard\"data-previewers=\"\"><code>xacro xacro_file &gt; urdf_file<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_e4d90dd = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_e4d90dd();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_e4d90dd );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5349114 elementor-widget elementor-widget-text-editor\" data-id=\"5349114\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Una vez que ya tengamos el archivo URDF realizaremos la comprobaci\u00f3n de la sintaxis mediante la ejecuci\u00f3n de la herramienta <i>check_urdf<\/i>\u00a0. Si no detecta errores, nos dar\u00e1 una salida como la del siguiente ejemplo.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-624693b elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"624693b\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-624693b\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-tomorrow\"\n            data-dark-theme=\"mdp-theme-tomorrow\"\n        >\n            \n                <pre class=\"language-markup copy-to-clipboard\"data-previewers=\"\"><code>user@ubuntu:~\/ros2_ws\/src\/mars_robot\/urdf$ check_urdf model.urdf\n\nrobot name is: mars_robot\n---------- Successfully Parsed XML ---------------\nroot Link: base_link has 5 child(ren)\n    child(1):  link_camera_frame\n        child(1):  link_camera_optical\n    child(2):  link_caster_wheel\n    child(3):  link_left_wheel\n    child(4):  link_lidar\n    child(5):  link_right_wheel\n<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_624693b = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_624693b();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_624693b );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-dbb69f7 elementor-widget elementor-widget-text-editor\" data-id=\"dbb69f7\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Tambi\u00e9n podemos usar la herramienta <i>urdf_to_graphiz<\/i> que nos crear\u00e1 un archivo <i>pdf<\/i> con una representaci\u00f3n de la estructura de nuestro modelo.\u00a0<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e44f91c elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"e44f91c\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-e44f91c\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-tomorrow\"\n            data-dark-theme=\"mdp-theme-tomorrow\"\n        >\n            \n                <pre class=\"language-shell-session copy-to-clipboard\"data-previewers=\"\"><code>urdf_to_graphiz urdf_file<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_e44f91c = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_e44f91c();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_e44f91c );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-256090b elementor-widget elementor-widget-text-editor\" data-id=\"256090b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Usando el mismo ejemplo el contenido del <i>pdf<\/i> generado ser\u00eda el siguiente.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b6b2f08 elementor-widget elementor-widget-image\" data-id=\"b6b2f08\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/urdf_to_graphiz.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"urdf_to_graphiz\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjYzOCwidXJsIjoiaHR0cHM6XC9cL3JvYm90aWNhLWZhY2lsLWNvbi1yb3MyLmVzXC93cC1jb250ZW50XC91cGxvYWRzXC8yMDIyXC8wNlwvdXJkZl90b19ncmFwaGl6LnBuZyJ9\">\n\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"420\" src=\"https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/urdf_to_graphiz-1024x420.png\" class=\"attachment-large size-large wp-image-2638\" alt=\"\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cb19948 elementor-widget elementor-widget-text-editor\" data-id=\"cb19948\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<h4>Verificaci\u00f3n del comportamiento de las articulaciones<\/h4><p>Otra cosa que podemos hacer para verificar que nuestro c\u00f3digo URDF es correcto es ver si los movimientos de las articulaciones son correctos. Para ello utilizaremos\u00a0<span style=\"color: #0170b9;\"><i><b>RVIZ2<\/b><\/i><\/span> para visualizar el robot y los paquetes <span style=\"color: #0170b9;\"><i><b>joint_state_publisher<\/b><\/i><\/span> y <strong><span style=\"color: #0170b9;\"><i>robot_state_publisher<\/i><\/span><\/strong>, los cuales publican el estado de las articulaciones y las transformaciones entre los distintos sistemas de referencia asociados a cada uno de los enlaces respectivamente. Con esta informaci\u00f3n RVIZ2 es capaz de representar el robot.<\/p><p>Por comodidad, en vez de ejecutar cada paquete en una consola diferente lo que vamos a hacer es crear uno nuevo, al que llamaremos por ejemplo <span style=\"color: #0170b9;\"><i><b>check_joints<\/b><\/i><\/span>, que simplemente va a contener un archivo <em>launch<\/em> que nos va a permitir ejecutarlos todos a la vez y al que adem\u00e1s pasaremos como un par\u00e1metro el nombre del archivo URDF que queremos probar.<\/p><p>El primer paso ser\u00e1 pues ir a la carpeta <i>src<\/i> de nuestro espacio de trabajo y crear este paquete. Para ello ejecutaremos los siguientes comandos desde el terminal, sustituyendo <i><\/i> por la ruta al espacio de trabajo:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5655f6d elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"5655f6d\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-5655f6d\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-tomorrow\"\n            data-dark-theme=\"mdp-theme-tomorrow\"\n        >\n            \n                <pre class=\"language-shell-session copy-to-clipboard\"data-previewers=\"\"><code>cd ~\/&lt;ws_path&gt;\/src \nros2 pkg create check_joints --build-type ament_python --dependencies rclpy <\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_5655f6d = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_5655f6d();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_5655f6d );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-988d92a elementor-widget elementor-widget-text-editor\" data-id=\"988d92a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>A continuaci\u00f3n a\u00f1adiremos las carpetas\u00a0<span style=\"color: #0170b9;\"><strong><i>launch<\/i><\/strong><\/span>\u00a0y <span style=\"color: #0170b9;\"><strong><i>config<\/i><\/strong><\/span> a nuestro paquete y en su interior crearemos los archivos <span style=\"color: #0170b9;\"><strong><i>check_joints.launch.py\u00a0 <\/i><\/strong><\/span>y <i><span style=\"color: #0170b9;\"><strong>config.rviz<\/strong><\/span>:<\/i><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b34f4b2 elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"b34f4b2\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-b34f4b2\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-tomorrow\"\n            data-dark-theme=\"mdp-theme-tomorrow\"\n        >\n            \n                <pre class=\"language-shell-session copy-to-clipboard\"data-previewers=\"\"><code>mkdir -p check_joints\/launch\nmkdir -p check_joints\/config\ncd check_joints\/launch\ntouch check_joints.launch.py\ncd ..\ncd config\ntouch config.rviz<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_b34f4b2 = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_b34f4b2();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_b34f4b2 );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c8e2ec4 elementor-widget elementor-widget-text-editor\" data-id=\"c8e2ec4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Abrimos el archivo config.rviz y copiamos el siguiente c\u00f3digo. La parte importante son las l\u00edneas donde se indica a RVIZ2 que cargue un modelo de robot cuya descripci\u00f3n es proporcionada por el topic <i>robot_description:<\/i><\/p><p>\u00a0<\/p><p style=\"padding-left: 80px;\"><em>Class: rviz_default_plugins\/RobotModel<\/em><br \/>&#8230;<br \/><em>&#8230;<\/em><br \/><em>Visual Enabled: true<\/em><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e4d7839 elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"e4d7839\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-e4d7839\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-xonokai\"\n            data-dark-theme=\"mdp-theme-xonokai\"\n        >\n            \n                <pre class=\"language-markup copy-to-clipboard\"data-previewers=\"\"><code>Panels:\n  - Class: rviz_common\/Displays\n    Help Height: 78\n    Name: Displays\n    Property Tree Widget:\n      Expanded:\n        - \/Global Options1\n        - \/Status1\n        - \/RobotModel1\n      Splitter Ratio: 0.5\n    Tree Height: 336\n  - Class: rviz_common\/Selection\n    Name: Selection\n  - Class: rviz_common\/Tool Properties\n    Expanded:\n      - \/2D Goal Pose1\n      - \/Publish Point1\n    Name: Tool Properties\n    Splitter Ratio: 0.5886790156364441\n  - Class: rviz_common\/Views\n    Expanded:\n      - \/Current View1\n    Name: Views\n    Splitter Ratio: 0.5\n  - Class: rviz_common\/Time\n    Experimental: false\n    Name: Time\n    SyncMode: 0\n    SyncSource: &quot;&quot;\n  - Class: rviz_visual_tools\/RvizVisualToolsGui\n    Name: RvizVisualToolsGui\nVisualization Manager:\n  Class: &quot;&quot;\n  Displays:\n    - Alpha: 0.5\n      Cell Size: 1\n      Class: rviz_default_plugins\/Grid\n      Color: 160; 160; 164\n      Enabled: true\n      Line Style:\n        Line Width: 0.029999999329447746\n        Value: Lines\n      Name: Grid\n      Normal Cell Count: 0\n      Offset:\n        X: 0\n        Y: 0\n        Z: 0\n      Plane: XY\n      Plane Cell Count: 10\n      Reference Frame: &lt;Fixed Frame&gt;\n      Value: true\n    - Alpha: 1\n      Class: rviz_default_plugins\/RobotModel\n      Collision Enabled: true\n      Description File: &quot;&quot;\n      Description Source: Topic\n      Description Topic:\n        Depth: 5\n        Durability Policy: Volatile\n        History Policy: Keep Last\n        Reliability Policy: Reliable\n        Value: robot_description\n      Enabled: true\n      Name: RobotModel\n      TF Prefix: &quot;&quot;\n      Update Interval: 0\n      Value: true\n      Visual Enabled: true\n  Enabled: true\n  Global Options:\n    Background Color: 48; 48; 48\n    Frame Rate: 30\n  Name: root\n  Tools:\n    - Class: rviz_default_plugins\/Interact\n      Hide Inactive Objects: true\n    - Class: rviz_default_plugins\/MoveCamera\n    - Class: rviz_default_plugins\/Select\n    - Class: rviz_default_plugins\/FocusCamera\n    - Class: rviz_default_plugins\/Measure\n      Line color: 128; 128; 0\n    - Class: rviz_default_plugins\/SetInitialPose\n      Covariance x: 0.25\n      Covariance y: 0.25\n      Covariance yaw: 0.06853891909122467\n      Topic:\n        Depth: 5\n        Durability Policy: Volatile\n        History Policy: Keep Last\n        Reliability Policy: Reliable\n        Value: \/initialpose\n    - Class: rviz_default_plugins\/SetGoal\n      Topic:\n        Depth: 5\n        Durability Policy: Volatile\n        History Policy: Keep Last\n        Reliability Policy: Reliable\n        Value: \/goal_pose\n    - Class: rviz_default_plugins\/PublishPoint\n      Single click: true\n      Topic:\n        Depth: 5\n        Durability Policy: Volatile\n        History Policy: Keep Last\n        Reliability Policy: Reliable\n        Value: \/clicked_point\n  Transformation:\n    Current:\n      Class: rviz_default_plugins\/TF\n  Value: true\n  Views:\n    Current:\n      Class: rviz_default_plugins\/Orbit\n      Distance: 3.969904661178589\n      Enable Stereo Rendering:\n        Stereo Eye Separation: 0.05999999865889549\n        Stereo Focal Distance: 1\n        Swap Stereo Eyes: false\n        Value: false\n      Focal Point:\n        X: 0.6851969957351685\n        Y: -0.14429132640361786\n        Z: 0.42723408341407776\n      Focal Shape Fixed Size: true\n      Focal Shape Size: 0.05000000074505806\n      Invert Z Axis: false\n      Name: Current View\n      Near Clip Distance: 0.009999999776482582\n      Pitch: 0.660398006439209\n      Target Frame: &lt;Fixed Frame&gt;\n      Value: Orbit (rviz)\n      Yaw: 5.8485822677612305\n    Saved: ~\nWindow Geometry:\n  Displays:\n    collapsed: false\n  Height: 704\n  Hide Left Dock: false\n  Hide Right Dock: false\n  QMainWindow State: 000000ff00000000fd00000004000000000000016400000222fc0200000009fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000001db000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb00000024005200760069007a00560069007300750061006c0054006f006f006c0073004700750069010000021e000000410000004100ffffff000000010000010f00000222fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d00000222000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004b00000003efc0100000002fb0000000800540069006d00650100000000000004b0000002eb00fffffffb0000000800540069006d00650100000000000004500000000000000000000002310000022200000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000\n  RvizVisualToolsGui:\n    collapsed: false\n  Selection:\n    collapsed: false\n  Time:\n    collapsed: false\n  Tool Properties:\n    collapsed: false\n  Views:\n    collapsed: false\n  Width: 1200\n  X: 529\n  Y: 161<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_e4d7839 = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_e4d7839();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_e4d7839 );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1a3108b elementor-widget elementor-widget-text-editor\" data-id=\"1a3108b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>El siguiente paso es editar el archivo <span style=\"color: #0170b9;\"><i><b>check_joints.launch.py<\/b><\/i><\/span> y pegar el siguiente c\u00f3digo.\u00a0\u00a0<span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">B\u00e1sicamente lo que hace es leer el archivo URDF que se le pase mediante el argumento <\/span><span style=\"font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\"><i>urdf_file<\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">, analizarlo para determinar cual es el enlace ra\u00edz y crear los nodos <\/span><span style=\"background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\"><i>rviz2<\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">, <\/span><span style=\"background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\"><i>robot_state_publisher<\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\"> y <\/span><span style=\"background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\"><i>joint_state_publisher_gui<\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">.<\/span><\/p><p><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">Lo m\u00e1s destacable del mismo es que los nodos no se crean directamente dentro de la funci\u00f3n\u00a0 <\/span><span style=\"font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\"><i>generate_launch_description( )<\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\"> que es lo habitual en un archivo <\/span><span style=\"font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\"><i>launch<\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">, sino que se hace en una nueva funci\u00f3n <\/span><span style=\"font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\"><i>setup_launch( )<\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">\u00a0que hemos creado y a la que se llama empleando <\/span><span style=\"background-color: var(--ast-global-color-4); color: #0170b9;\"><i><b>OpaqueFunction<\/b><\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">.\u00a0<\/span><\/p><p><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">El motivo es que no se puede acceder al valor que se pasa a un argumento para usarlo\u00a0<\/span><span style=\"background-color: var(--ast-global-color-4); color: var(--ast-global-color-3);\">como si fuera una variable python en<\/span><span style=\"font-style: inherit; font-weight: inherit; color: var(--ast-global-color-3); background-color: var(--ast-global-color-4);\">\u00a0la funci\u00f3n <\/span><span style=\"font-style: inherit; font-weight: inherit; color: var(--ast-global-color-3); background-color: var(--ast-global-color-4);\"><i>generate_launch_description( ),<\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; color: var(--ast-global-color-3); background-color: var(--ast-global-color-4);\"> pero necesitamos conocer el nombre del archivo URDF para poder abrirlo, encontrar el enlace ra\u00edz y pasarlo como argumento del nodo RVIZ2. <\/span><span style=\"font-weight: inherit; color: var(--ast-global-color-3); background-color: var(--ast-global-color-4);\"><i>OpaqueFunction<\/i><\/span><span style=\"font-style: inherit; font-weight: inherit; color: var(--ast-global-color-3); background-color: var(--ast-global-color-4);\"> permite llamar a esta nueva funci\u00f3n donde podemos obtener el valor del argumento mediante <\/span><strong><span style=\"color: #0170b9;\"><em style=\"font-weight: inherit; background-color: var(--ast-global-color-4);\"><span style=\"background-color: var(--ast-global-color-4);\">LaunchConfigurati<\/span><\/em><\/span><\/strong><span style=\"font-style: inherit; font-weight: inherit; color: var(--ast-global-color-3); background-color: var(--ast-global-color-4);\"><strong><span style=\"color: #0170b9;\"><em>on(&#8216;urdf_file&#8217;).perform(context)<\/em><\/span><\/strong>.<\/span><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a0599e8 elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"a0599e8\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-a0599e8\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-xonokai\"\n            data-dark-theme=\"mdp-theme-xonokai\"\n        >\n            \n                <pre class=\"language-python copy-to-clipboard\"data-previewers=\"\"><code>import xacro, os   \nimport xml.etree.ElementTree as ET\n\nfrom launch.actions import OpaqueFunction\nfrom ament_index_python.packages import get_package_share_directory\nfrom launch.actions import DeclareLaunchArgument\nfrom launch import LaunchDescription\nfrom launch_ros.actions import Node\nfrom launch.substitutions import Command, LaunchConfiguration\n\n\ndef generate_launch_description():\n\n    # Declara el argumento &#039;urdf_file&#039; que proporciona el nombre del archivo que\n    # contiene el codigo URDF de nuestro modelo. \n    urdf_file_arg = DeclareLaunchArgument(\n        &quot;urdf_file&quot;, default_value=&#039;&#039;, description=&#039;Name of URDF file.&#039;\n    )\n \n    return LaunchDescription([\n        urdf_file_arg,\n        OpaqueFunction(function=setup_launch)\n    ])\n\ndef setup_launch(context, *args, **kwargs):\n\n    # Obtiene el valor del argumento &#039;urdf_file&#039;.\n    urdf_file = LaunchConfiguration(&#039;urdf_file&#039;).perform(context)\n\n    # Genera una cadena de texto que contene el c&oacute;digo URDF.\n    doc = xacro.parse(open(urdf_file))\n    xacro.process_doc(doc)\n    urdf_code = doc.toxml()\n\n    # Genera una estructura de arbol con la informaci&oacute;n XML del codigo URDF.\n    tree = ET.ElementTree(ET.fromstring(urdf_code))\n    root = tree.getroot()\n\n    # Recorre el arbol para crear una lista con todos los enlaces presentes en el modelo URDF.\n    links = []\n    for item in root.iter(&#039;link&#039;):\n        links.append(item.attrib[&#039;name&#039;])\n        print(item.tag, &quot;: &quot;, item.attrib[&#039;name&#039;])\n\n    # Obtiene el enlace raiz. Para ello elimina de la lista los enlaces que aparecen como \n    # secundarios en las articulaciones.\n    for item in root.iter(&#039;joint&#039;):\n        print(item.tag, &quot;: &quot;, item.attrib[&#039;name&#039;])\n        for sub_item in item.iter(&#039;parent&#039;):\n            print(&quot;  |--- &quot;, sub_item.tag, &quot;: &quot;, sub_item.attrib[&#039;link&#039;])\n        for sub_item in item.iter(&#039;child&#039;):\n            print(&quot;  |--- &quot;, sub_item.tag, &quot;: &quot;, sub_item.attrib[&#039;link&#039;])\n            links.remove(sub_item.attrib[&#039;link&#039;])\n\n    if len(links)&gt;1:\n        print(&quot;Error: el archivo URDF contiene m&aacute;s de un enlace raiz.&quot;)\n        return\n\n    root_link = links[0]\n    print(&quot;root_link: &quot;, root_link)\n\n    # Obtiene la direcci&oacute;n del archivo rviz2.config que contiene la configuraci&oacute;n para RVIZ2.\n    rviz2_config = os.path.join(get_package_share_directory(&#039;check_joints&#039;), &#039;config\/config.rviz&#039;)\n\n    # Crea y configura el nodo RVIZ2, el cual permite visualizar el modelo URDF a partir de\n    # la informaci&oacute;n que proporciona el nodo ROBOT_STATE_PUBLISHER. \n    node_rviz2 = Node(\n        package=&#039;rviz2&#039;,\n        executable=&#039;rviz2&#039;,\n        name=&#039;rviz2&#039;,\n        arguments=[&#039;-d&#039;, rviz2_config, &#039;-f&#039;, root_link],\n        output={&#039;both&#039;: &#039;log&#039;},\n    )\n\n    # Crea y configura el nodo JOINT_STATE_PUBLISHER_GUI, el cual permite simular el estado de\n    # las articulaciones.\n    node_joint_state_publisher_gui = Node(\n        package=&#039;joint_state_publisher_gui&#039;,\n        executable=&#039;joint_state_publisher_gui&#039;,\n        name=&#039;joint_state_publisher_gui&#039;,\n        arguments=[&#039;--ros-args&#039;, &#039;--log-level&#039;, &#039;error&#039;],\n        output={&#039;both&#039;: &#039;log&#039;},\n    )\n\n    # Crea y configura el nodo ROBOT_STATE_PUBLISHER, el cual resuelve la cinematica \n    # directa del robot a partir de la informaci&oacute;n que proporciona el nodo\n    # JOINT_STATE_PUBLISHER_GUI.\n    node_robot_state_publisher = Node(\n        package=&#039;robot_state_publisher&#039;,\n        executable=&#039;robot_state_publisher&#039;,\n        name=&#039;robot_state_publisher&#039;,\n        parameters=[{&#039;robot_description&#039;: Command([&#039;xacro &#039;, urdf_file])}],\n        arguments=[&#039;--ros-args&#039;, &#039;--log-level&#039;, &#039;error&#039;],\n        output={&#039;both&#039;: &#039;log&#039;},\n    )\n\n\n    # Devuelve los nodos creados.\n    return [node_rviz2, node_robot_state_publisher, node_joint_state_publisher_gui]<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_a0599e8 = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_a0599e8();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_a0599e8 );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-13e482d elementor-widget elementor-widget-text-editor\" data-id=\"13e482d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Por ultimo editamos el archivo <span style=\"color: #0170b9;\"><strong><i>setup.py<\/i><\/strong><\/span> del paquete e insertamos las dos l\u00edneas que aparecen al final de la lista <i>data_files<\/i> para que se incluya en la instalaci\u00f3n del mismo el contenido de las carpetas <i>launch<\/i> y <i>config<\/i>.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-84f5f8a elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"84f5f8a\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-84f5f8a\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-xonokai\"\n            data-dark-theme=\"mdp-theme-xonokai\"\n        >\n            \n                <pre class=\"language-python copy-to-clipboard\"data-previewers=\"\"><code>import os\nfrom glob import glob\nfrom setuptools import setup\n\npackage_name = &#039;check_joints&#039;\n\nsetup(\n    name=package_name,\n    version=&#039;0.0.0&#039;,\n    packages=[package_name],\n    data_files=[\n        (&#039;share\/ament_index\/resource_index\/packages&#039;,\n            [&#039;resource\/&#039; + package_name]),\n        (&#039;share\/&#039; + package_name, [&#039;package.xml&#039;]),\n        (os.path.join(&#039;share&#039;, package_name, &#039;launch&#039;), glob(&#039;launch\/*.launch.py&#039;)),\n        (os.path.join(&#039;share&#039;, package_name, &#039;config&#039;), glob(&#039;config\/*.rviz&#039;)),\n    ],\n    install_requires=[&#039;setuptools&#039;],\n    zip_safe=True,\n    maintainer=&#039;ros&#039;,\n    maintainer_email=&#039;ros@todo.todo&#039;,\n    description=&#039;TODO: Package description&#039;,\n    license=&#039;TODO: License declaration&#039;,\n    tests_require=[&#039;pytest&#039;],\n    entry_points={\n        &#039;console_scripts&#039;: [\n        ],\n    },\n)<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_84f5f8a = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_84f5f8a();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_84f5f8a );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6bd655a elementor-widget elementor-widget-text-editor\" data-id=\"6bd655a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Y ya solo nos queda compilar el paquete con el comando <i>colcon build<\/i>.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6f3a75a elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"6f3a75a\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-6f3a75a\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-tomorrow\"\n            data-dark-theme=\"mdp-theme-tomorrow\"\n        >\n            \n                <pre class=\"language-bash copy-to-clipboard\"data-previewers=\"\"><code>colcon build --packages-select check_joints<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_6f3a75a = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_6f3a75a();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_6f3a75a );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2f7e6ad elementor-widget elementor-widget-text-editor\" data-id=\"2f7e6ad\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Una vez que ya tenemos nuestro paquete listo podemos probar nuestro modelo ejecutando el archivo launch, al que pasaremos como par\u00e1metro el nombre del archivo URDF.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5e2de9c elementor-widget elementor-widget-mdp-coder-elementor\" data-id=\"5e2de9c\" data-element_type=\"widget\" data-widget_type=\"mdp-coder-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t        <!-- Start Coder for Elementor WordPress Plugin -->\n        <div\n            id=\"mdp-coder-5e2de9c\"\n            class=\"mdp-coder-elementor-box\"\n            data-theme=\"mdp-theme-tomorrow\"\n            data-dark-theme=\"mdp-theme-tomorrow\"\n        >\n            \n                <pre class=\"language-bash copy-to-clipboard\"data-previewers=\"\"><code>ros2 launch check_joints check_joints.launch.py urdf_file:=model.urdf<\/code><\/pre>\n                    <\/div>\n                <script>\n            \"use strict\";\n\n            \/** Handler when the DOM is fully loaded. *\/\n            let callback_5e2de9c = function() {\n\n                \/** Set theme for coder widget. *\/\n                function setTheme() {\n\n                    \/** Foreach Code Widget. *\/\n                    let coderBoxes = document.querySelectorAll( '.mdp-coder-elementor-box' );\n\n                    for ( let coderBox of coderBoxes ) {\n\n                        let lightTheme = coderBox.dataset.theme;\n                        let darkTheme = coderBox.dataset.darkTheme;\n\n                        coderBox.className = '';\n                        if ( window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + darkTheme;\n\n                        } else {\n\n                            coderBox.className = 'mdp-coder-elementor-box ' + lightTheme;\n\n                        }\n\n                    }\n\n                }\n                setTheme();\n\n\n                \/** Watch for changes color-scheme. *\/\n                window.matchMedia(\"(prefers-color-scheme: dark)\").addListener( function() {\n                    setTheme();\n                } );\n\n                \n                if ( typeof Prism !== 'undefined' ) {\n\n                    Prism.plugins.autoloader.languages_path = 'https:\/\/robotica-facil-con-ros2.es\/wp-content\/plugins\/coder-elementor\/js\/prism\/components\/';\n                    Prism.highlightAll();\n                    Prism.fileHighlight();\n\n                }\n\n                \n            };\n\n            if (\n                document.readyState === \"complete\" ||\n                ( document.readyState !== \"loading\" && !document.documentElement.doScroll )\n            ) {\n                callback_5e2de9c();\n            } else {\n                document.addEventListener( \"DOMContentLoaded\", callback_5e2de9c );\n            }\n\n        <\/script>\n                <!-- End Coder for Elementor WordPress Plugin -->\n\n        \t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d84895a elementor-widget elementor-widget-text-editor\" data-id=\"d84895a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Se nos abrir\u00e1n dos ventanas: una con RVIZ2 donde podremos visualizar nuestro modelo y otra generada por el nodo <i>joint_state_publisher_gui<\/i> donde aparecen todas las articulaciones que no sean fijas, en la que podremos ir variando los valores asociados al estado de las mismas (\u00e1ngulos de giro o desplazamientos).<\/p><p>De este modo podemos ir moviendo las articulaciones y viendo simult\u00e1neamente en RVIZ2 si el comportamiento es el que deseamos.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6cf7eb1 elementor-widget elementor-widget-image\" data-id=\"6cf7eb1\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/check-urdf-files-screenshot2.png\" data-elementor-open-lightbox=\"no\">\n\t\t\t\t\t\t\t<img decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/check-urdf-files-screenshot2-1024x576.png\" class=\"attachment-large size-large wp-image-2765\" alt=\"\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5a53c0d elementor-widget elementor-widget-text-editor\" data-id=\"5a53c0d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Puedes descargar el paquete <a href=\"https:\/\/github.com\/joseecm-github\/check_joints\">check_joints<\/a> desde Github.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Aprende como chequear tus archivos URDF e identificar posibles problemas.<\/p>\n","protected":false},"author":1,"featured_media":2770,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[5,10],"tags":[12,7,11],"class_list":["post-2595","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ros2","category-simulacion","tag-gazebo","tag-ros2","tag-urdf"],"aioseo_notices":[],"rttpg_featured_image_url":{"full":["https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/Screenshot-from-2022-07-19-21-28-06-2.png",747,491,false],"landscape":["https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/Screenshot-from-2022-07-19-21-28-06-2.png",747,491,false],"portraits":["https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/Screenshot-from-2022-07-19-21-28-06-2.png",747,491,false],"thumbnail":["https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/Screenshot-from-2022-07-19-21-28-06-2-150x150.png",150,150,true],"medium":["https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/Screenshot-from-2022-07-19-21-28-06-2-300x197.png",300,197,true],"large":["https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/Screenshot-from-2022-07-19-21-28-06-2.png",747,491,false],"1536x1536":["https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/Screenshot-from-2022-07-19-21-28-06-2.png",747,491,false],"2048x2048":["https:\/\/robotica-facil-con-ros2.es\/wp-content\/uploads\/2022\/06\/Screenshot-from-2022-07-19-21-28-06-2.png",747,491,false]},"rttpg_author":{"display_name":"Jose Enrique Cabrera","author_link":"https:\/\/robotica-facil-con-ros2.es\/?author=1"},"rttpg_comment":0,"rttpg_category":"<a href=\"https:\/\/robotica-facil-con-ros2.es\/?cat=5\" rel=\"category\">ROS2<\/a> <a href=\"https:\/\/robotica-facil-con-ros2.es\/?cat=10\" rel=\"category\">SIMULACI\u00d3N<\/a>","rttpg_excerpt":"Aprende como chequear tus archivos URDF e identificar posibles problemas.","_links":{"self":[{"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=\/wp\/v2\/posts\/2595","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2595"}],"version-history":[{"count":188,"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=\/wp\/v2\/posts\/2595\/revisions"}],"predecessor-version":[{"id":5641,"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=\/wp\/v2\/posts\/2595\/revisions\/5641"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=\/wp\/v2\/media\/2770"}],"wp:attachment":[{"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2595"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2595"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/robotica-facil-con-ros2.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2595"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}