{"id":75,"date":"2017-04-13T20:20:48","date_gmt":"2017-04-13T19:20:48","guid":{"rendered":"http:\/\/marvinferber.net\/?p=75"},"modified":"2017-04-13T20:28:47","modified_gmt":"2017-04-13T19:28:47","slug":"ros-and-node-red-part-3-managing-ros-launch-configurations","status":"publish","type":"post","link":"https:\/\/marvinferber.net\/?p=75","title":{"rendered":"ROS and Node-RED Part 3: Managing ROS launch configurations"},"content":{"rendered":"<p>Once you start using ROS you will have to write launch files that combine a set of ROS nodes to a meaningful robot runtime configuration. I personally found it always tedious to edit these files, combine functionalities, adapt parameters and restart the whole launch file from command line. In this third tutorial, I present my Node-RED approach of handing launch configurations and parameters.<\/p>\n<h2>Roslaunch from Node-RED<\/h2>\n<p>It is mandatory to have configured a ROS command line environment when you start the Node-RED server. This can be achieved easily when you have sourced the ROS setup in your .bashrc. Btw. we are still on Ubuntu 14.04 as you might have guessed from the <a href=\"http:\/\/marvinferber.net\/?p=14\">first tutorial<\/a>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">source \/opt\/ros\/indigo\/setup.bash\r\nsource ~\/catkin_ws\/devel\/setup.bash\r\n<\/pre>\n<p>Be careful when using Node-RED as a system service in Ubuntu using upstart. I was not able to execute the above two lines in an upstart script. My solution when Node-RED should be started at system startup is to auto login a normal user (see this <a href=\"https:\/\/wiki.ubuntuusers.de\/Autologin\/\">link how to configure autologin<\/a>, in German, sorry &#8211;&gt; leave me a comment for any similar English explanation) and add the ROS setup and Node-RED startup to this users .bashrc. However, this solution may be a security risk, if a keyboard is plugged to the PC.<\/p>\n<p>My roslaunch flow is then performed in three steps in Node-RED when the flow is triggered, e.g., using an inject node:<\/p>\n<ol>\n<li>Create a roslaunch configuration in Node-RED using a template node.<\/li>\n<li>Write this configuration to a temporary file using a file node. (wait a second before the file is written using delay node)<\/li>\n<li>Execute a roslaunch command on the temporary file using an exec node.<\/li>\n<\/ol>\n<p>A flow implementing the above three steps is given below.<img loading=\"lazy\" decoding=\"async\" class=\" wp-image-87 aligncenter\" src=\"http:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-214645-e1491767287522.png\" alt=\"\" width=\"935\" height=\"354\" srcset=\"https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-214645-e1491767287522.png 1051w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-214645-e1491767287522-300x114.png 300w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-214645-e1491767287522-768x291.png 768w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-214645-e1491767287522-1024x388.png 1024w\" sizes=\"auto, (max-width: 935px) 100vw, 935px\" \/><\/p>\n<div style=\"overflow: auto; max-height: 600px;\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">[\r\n    {\r\n        \"id\": \"cc9a367a.dd0918\",\r\n        \"type\": \"tab\",\r\n        \"label\": \"Test1\"\r\n    },\r\n    {\r\n        \"id\": \"b73657b6.347178\",\r\n        \"type\": \"template\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"minimal.launch\",\r\n        \"field\": \"payload\",\r\n        \"fieldType\": \"msg\",\r\n        \"format\": \"html\",\r\n        \"syntax\": \"plain\",\r\n        \"template\": \"&lt;launch&gt;\\n  &lt;!-- Turtlebot --&gt;\\n  &lt;arg name=\\\"base\\\"              default=\\\"$(env TURTLEBOT_BASE)\\\"         doc=\\\"mobile base type [create, roomba]\\\"\/&gt;\\n  &lt;arg name=\\\"battery\\\"           default=\\\"$(env TURTLEBOT_BATTERY)\\\"      doc=\\\"kernel provided locatio for battery info, use \/proc\/acpi\/battery\/BAT0 in 2.6 or earlier kernels.\\\" \/&gt;\\n  &lt;arg name=\\\"stacks\\\"            default=\\\"$(env TURTLEBOT_STACKS)\\\"       doc=\\\"stack type displayed in visualisation\/simulation [circles, hexagons]\\\"\/&gt;\\n  &lt;arg name=\\\"3d_sensor\\\"         default=\\\"$(env TURTLEBOT_3D_SENSOR)\\\"    doc=\\\"3d sensor types [kinect, asux_xtion_pro]\\\"\/&gt;\\n  &lt;arg name=\\\"simulation\\\"        default=\\\"$(env TURTLEBOT_SIMULATION)\\\"   doc=\\\"set flags to indicate this turtle is run in simulation mode.\\\"\/&gt;\\n  &lt;arg name=\\\"serialport\\\"        default=\\\"$(env TURTLEBOT_SERIAL_PORT)\\\"  doc=\\\"used by create to configure the port it is connected on [\/dev\/ttyUSB0, \/dev\/ttyS0]\\\"\/&gt;\\n  &lt;arg name=\\\"robot_name\\\"        default=\\\"$(env TURTLEBOT_NAME)\\\"         doc=\\\"used as a unique identifier and occasionally to preconfigure root namespaces, gateway\/zeroconf ids etc.\\\"\/&gt;\\n  &lt;arg name=\\\"robot_type\\\"        default=\\\"$(env TURTLEBOT_TYPE)\\\"         doc=\\\"just in case you are considering a 'variant' and want to make use of this.\\\"\/&gt;\\n\\n  &lt;param name=\\\"\/use_sim_time\\\" value=\\\"$(arg simulation)\\\"\/&gt;\\n\\n  &lt;include file=\\\"$(find turtlebot_bringup)\/launch\/includes\/robot.launch.xml\\\"&gt;\\n    &lt;arg name=\\\"base\\\" value=\\\"$(arg base)\\\" \/&gt;\\n    &lt;arg name=\\\"stacks\\\" value=\\\"$(arg stacks)\\\" \/&gt;\\n    &lt;arg name=\\\"3d_sensor\\\" value=\\\"$(arg 3d_sensor)\\\" \/&gt;\\n  &lt;\/include&gt;\\n  &lt;include file=\\\"$(find turtlebot_bringup)\/launch\/includes\/mobile_base.launch.xml\\\"&gt;\\n    &lt;arg name=\\\"base\\\" value=\\\"$(arg base)\\\" \/&gt;\\n    &lt;arg name=\\\"serialport\\\" value=\\\"$(arg serialport)\\\" \/&gt;\\n  &lt;\/include&gt;\\n  &lt;!-- Rosbridge --&gt;\\n  &lt;arg name=\\\"port\\\" default=\\\"9090\\\" \/&gt;\\n  &lt;arg name=\\\"address\\\" default=\\\"\\\" \/&gt;\\n  &lt;arg name=\\\"ssl\\\" default=\\\"false\\\" \/&gt;\\n  &lt;arg name=\\\"certfile\\\" default=\\\"\\\"\/&gt;\\n  &lt;arg name=\\\"keyfile\\\" default=\\\"\\\" \/&gt;\\n\\n  &lt;arg name=\\\"retry_startup_delay\\\" default=\\\"5\\\" \/&gt;\\n\\n  &lt;arg name=\\\"fragment_timeout\\\" default=\\\"600\\\" \/&gt;\\n  &lt;arg name=\\\"delay_between_messages\\\" default=\\\"0\\\" \/&gt;\\n  &lt;arg name=\\\"max_message_size\\\" default=\\\"None\\\" \/&gt;\\n\\n  &lt;arg name=\\\"authenticate\\\" default=\\\"false\\\" \/&gt;\\n\\n  &lt;group if=\\\"$(arg ssl)\\\"&gt;\\n    &lt;node name=\\\"rosbridge_websocket\\\" pkg=\\\"rosbridge_server\\\" type=\\\"rosbridge_websocket\\\" output=\\\"screen\\\"&gt;\\n      &lt;param name=\\\"certfile\\\" value=\\\"$(arg certfile)\\\" \/&gt;\\n      &lt;param name=\\\"keyfile\\\" value=\\\"$(arg keyfile)\\\" \/&gt;\\n      &lt;param name=\\\"authenticate\\\" value=\\\"$(arg authenticate)\\\" \/&gt;\\n      &lt;param name=\\\"port\\\" value=\\\"$(arg port)\\\"\/&gt;\\n      &lt;param name=\\\"address\\\" value=\\\"$(arg address)\\\"\/&gt;\\n      &lt;param name=\\\"retry_startup_delay\\\" value=\\\"$(arg retry_startup_delay)\\\"\/&gt;\\n      &lt;param name=\\\"fragment_timeout\\\" value=\\\"$(arg fragment_timeout)\\\"\/&gt;\\n      &lt;param name=\\\"delay_between_messages\\\" value=\\\"$(arg delay_between_messages)\\\"\/&gt;\\n      &lt;param name=\\\"max_message_size\\\" value=\\\"$(arg max_message_size)\\\"\/&gt;\\n    &lt;\/node&gt;\\n  &lt;\/group&gt;\\n  &lt;group unless=\\\"$(arg ssl)\\\"&gt;\\n    &lt;node name=\\\"rosbridge_websocket\\\" pkg=\\\"rosbridge_server\\\" type=\\\"rosbridge_websocket\\\" output=\\\"screen\\\"&gt;\\n      &lt;param name=\\\"authenticate\\\" value=\\\"$(arg authenticate)\\\" \/&gt;\\n      &lt;param name=\\\"port\\\" value=\\\"$(arg port)\\\"\/&gt;\\n      &lt;param name=\\\"address\\\" value=\\\"$(arg address)\\\"\/&gt;\\n      &lt;param name=\\\"retry_startup_delay\\\" value=\\\"$(arg retry_startup_delay)\\\"\/&gt;\\n      &lt;param name=\\\"fragment_timeout\\\" value=\\\"$(arg fragment_timeout)\\\"\/&gt;\\n      &lt;param name=\\\"delay_between_messages\\\" value=\\\"$(arg delay_between_messages)\\\"\/&gt;\\n      &lt;param name=\\\"max_message_size\\\" value=\\\"$(arg max_message_size)\\\"\/&gt;\\n    &lt;\/node&gt;\\n  &lt;\/group&gt;\\n\\n  &lt;node name=\\\"rosapi\\\" pkg=\\\"rosapi\\\" type=\\\"rosapi_node\\\" \/&gt;\\n&lt;\/launch&gt;\\n\",\r\n        \"x\": 260,\r\n        \"y\": 280,\r\n        \"wires\": [\r\n            [\r\n                \"e397f13b.7f1ea\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"3e55c524.39868a\",\r\n        \"type\": \"inject\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"Start\",\r\n        \"topic\": \"\",\r\n        \"payload\": \"\",\r\n        \"payloadType\": \"date\",\r\n        \"repeat\": \"\",\r\n        \"crontab\": \"\",\r\n        \"once\": false,\r\n        \"x\": 110,\r\n        \"y\": 280,\r\n        \"wires\": [\r\n            [\r\n                \"b73657b6.347178\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"4062327e.354b8c\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"content\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"payload\",\r\n        \"x\": 920,\r\n        \"y\": 200,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"6e3567b.42d3098\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"filename\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"filename\",\r\n        \"x\": 920,\r\n        \"y\": 140,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"e397f13b.7f1ea\",\r\n        \"type\": \"function\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"Convert Filename\",\r\n        \"func\": \"msg.filename = \\\"\/tmp\/\\\" + parseInt( new Date().getTime()) + \\\".launch\\\"\\nreturn msg;\",\r\n        \"outputs\": 1,\r\n        \"noerr\": 0,\r\n        \"x\": 450,\r\n        \"y\": 280,\r\n        \"wires\": [\r\n            [\r\n                \"29bdc1.1329624\",\r\n                \"343cb1cc.66fa6e\",\r\n                \"6e3567b.42d3098\",\r\n                \"4062327e.354b8c\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"29bdc1.1329624\",\r\n        \"type\": \"file\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"write launchfile\",\r\n        \"filename\": \"\",\r\n        \"appendNewline\": true,\r\n        \"createDir\": false,\r\n        \"overwriteFile\": \"false\",\r\n        \"x\": 720,\r\n        \"y\": 280,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"343cb1cc.66fa6e\",\r\n        \"type\": \"delay\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"Wait 1s\",\r\n        \"pauseType\": \"delay\",\r\n        \"timeout\": \"1\",\r\n        \"timeoutUnits\": \"seconds\",\r\n        \"rate\": \"1\",\r\n        \"nbRateUnits\": \"1\",\r\n        \"rateUnits\": \"second\",\r\n        \"randomFirst\": \"1\",\r\n        \"randomLast\": \"5\",\r\n        \"randomUnits\": \"seconds\",\r\n        \"drop\": false,\r\n        \"x\": 240,\r\n        \"y\": 400,\r\n        \"wires\": [\r\n            [\r\n                \"569f5f6e.3d6b4\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"3f9b0113.e9a65e\",\r\n        \"type\": \"exec\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"command\": \"roslaunch \",\r\n        \"addpay\": true,\r\n        \"append\": \"\",\r\n        \"useSpawn\": \"\",\r\n        \"timer\": \"\",\r\n        \"name\": \"\",\r\n        \"x\": 560,\r\n        \"y\": 400,\r\n        \"wires\": [\r\n            [\r\n                \"81ca8c0d.05b86\"\r\n            ],\r\n            [\r\n                \"380f8a22.6be1e6\"\r\n            ],\r\n            [\r\n                \"c640c322.33cef\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"81ca8c0d.05b86\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"stdout\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"payload\",\r\n        \"x\": 910,\r\n        \"y\": 340,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"380f8a22.6be1e6\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"stderr\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"payload\",\r\n        \"x\": 910,\r\n        \"y\": 380,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"c640c322.33cef\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"return code\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"payload\",\r\n        \"x\": 930,\r\n        \"y\": 420,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"569f5f6e.3d6b4\",\r\n        \"type\": \"change\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"Set Launchfile\",\r\n        \"rules\": [\r\n            {\r\n                \"t\": \"set\",\r\n                \"p\": \"payload\",\r\n                \"pt\": \"msg\",\r\n                \"to\": \"filename\",\r\n                \"tot\": \"msg\"\r\n            }\r\n        ],\r\n        \"action\": \"\",\r\n        \"property\": \"\",\r\n        \"from\": \"\",\r\n        \"to\": \"\",\r\n        \"reg\": false,\r\n        \"x\": 400,\r\n        \"y\": 400,\r\n        \"wires\": [\r\n            [\r\n                \"3f9b0113.e9a65e\"\r\n            ]\r\n        ]\r\n    }\r\n]<\/pre>\n<\/div>\n<h2>Adding flexibility<\/h2>\n<p>So far, we cannot combine different launch file sections on demand, since we only have one template node to produce the content. We have to look a bit deeper into the template node that is used to produce the content of the launch file. First, we split the node into many in order to combine various launchfile sections at runtime. As an example, we split the minimal.launch that is used to startup a basic Turtlebot 2 configuration into a header, footer and content part of the launch file. Furthermore, we add a content part containing the launch configuration for an USB Camera 3D Sensor. The image below is showing the result.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-89 aligncenter\" src=\"http:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-220756-e1491768518622.png\" alt=\"\" width=\"826\" height=\"326\" srcset=\"https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-220756-e1491768518622.png 1056w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-220756-e1491768518622-300x118.png 300w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-220756-e1491768518622-768x303.png 768w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-09-220756-e1491768518622-1024x404.png 1024w\" sizes=\"auto, (max-width: 826px) 100vw, 826px\" \/><\/p>\n<figure id=\"attachment_96\" aria-describedby=\"caption-attachment-96\" style=\"width: 380px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-96\" src=\"http:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-13-210526-e1492110863818.png\" alt=\"\" width=\"380\" height=\"190\" srcset=\"https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-13-210526-e1492110863818.png 470w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-13-210526-e1492110863818-300x150.png 300w\" sizes=\"auto, (max-width: 380px) 100vw, 380px\" \/><figcaption id=\"caption-attachment-96\" class=\"wp-caption-text\">3D sensor left out from launchfile<\/figcaption><\/figure>\n<p>We are now able to omit the 3D sensor in each roslaunch simply by drawing a wire directly from minimal.launch to &lt;\/launch&gt;. As a result, launch files can be composed from text modules on demand. No launch file editing is needed anymore. In a next step, we add even more flexibility by making launch file parameters explicitly adaptable as Node-RED variables.<\/p>\n<p>The resulting flow can be copy &amp; pasted from below.<\/p>\n<div style=\"overflow: auto; max-height: 600px;\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">[\r\n    {\r\n        \"id\": \"cc9a367a.dd0918\",\r\n        \"type\": \"tab\",\r\n        \"label\": \"Test1\"\r\n    },\r\n    {\r\n        \"id\": \"b73657b6.347178\",\r\n        \"type\": \"template\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"minimal.launch\",\r\n        \"field\": \"payload\",\r\n        \"fieldType\": \"msg\",\r\n        \"format\": \"html\",\r\n        \"syntax\": \"mustache\",\r\n        \"template\": \"{{&amp;payload}}  \\n  &lt;!-- Turtlebot --&gt;\\n  &lt;arg name=\\\"base\\\"              default=\\\"$(env TURTLEBOT_BASE)\\\"         doc=\\\"mobile base type [create, roomba]\\\"\/&gt;\\n  &lt;arg name=\\\"battery\\\"           default=\\\"$(env TURTLEBOT_BATTERY)\\\"      doc=\\\"kernel provided locatio for battery info, use \/proc\/acpi\/battery\/BAT0 in 2.6 or earlier kernels.\\\" \/&gt;\\n  &lt;arg name=\\\"stacks\\\"            default=\\\"$(env TURTLEBOT_STACKS)\\\"       doc=\\\"stack type displayed in visualisation\/simulation [circles, hexagons]\\\"\/&gt;\\n  &lt;arg name=\\\"3d_sensor\\\"         default=\\\"$(env TURTLEBOT_3D_SENSOR)\\\"    doc=\\\"3d sensor types [kinect, asux_xtion_pro]\\\"\/&gt;\\n  &lt;arg name=\\\"simulation\\\"        default=\\\"$(env TURTLEBOT_SIMULATION)\\\"   doc=\\\"set flags to indicate this turtle is run in simulation mode.\\\"\/&gt;\\n  &lt;arg name=\\\"serialport\\\"        default=\\\"$(env TURTLEBOT_SERIAL_PORT)\\\"  doc=\\\"used by create to configure the port it is connected on [\/dev\/ttyUSB0, \/dev\/ttyS0]\\\"\/&gt;\\n  &lt;arg name=\\\"robot_name\\\"        default=\\\"$(env TURTLEBOT_NAME)\\\"         doc=\\\"used as a unique identifier and occasionally to preconfigure root namespaces, gateway\/zeroconf ids etc.\\\"\/&gt;\\n  &lt;arg name=\\\"robot_type\\\"        default=\\\"$(env TURTLEBOT_TYPE)\\\"         doc=\\\"just in case you are considering a 'variant' and want to make use of this.\\\"\/&gt;\\n\\n  &lt;param name=\\\"\/use_sim_time\\\" value=\\\"$(arg simulation)\\\"\/&gt;\\n\\n  &lt;include file=\\\"$(find turtlebot_bringup)\/launch\/includes\/robot.launch.xml\\\"&gt;\\n    &lt;arg name=\\\"base\\\" value=\\\"$(arg base)\\\" \/&gt;\\n    &lt;arg name=\\\"stacks\\\" value=\\\"$(arg stacks)\\\" \/&gt;\\n    &lt;arg name=\\\"3d_sensor\\\" value=\\\"$(arg 3d_sensor)\\\" \/&gt;\\n  &lt;\/include&gt;\\n  &lt;include file=\\\"$(find turtlebot_bringup)\/launch\/includes\/mobile_base.launch.xml\\\"&gt;\\n    &lt;arg name=\\\"base\\\" value=\\\"$(arg base)\\\" \/&gt;\\n    &lt;arg name=\\\"serialport\\\" value=\\\"$(arg serialport)\\\" \/&gt;\\n  &lt;\/include&gt;\\n  &lt;!-- Rosbridge --&gt;\\n  &lt;arg name=\\\"port\\\" default=\\\"9090\\\" \/&gt;\\n  &lt;arg name=\\\"address\\\" default=\\\"\\\" \/&gt;\\n  &lt;arg name=\\\"ssl\\\" default=\\\"false\\\" \/&gt;\\n  &lt;arg name=\\\"certfile\\\" default=\\\"\\\"\/&gt;\\n  &lt;arg name=\\\"keyfile\\\" default=\\\"\\\" \/&gt;\\n\\n  &lt;arg name=\\\"retry_startup_delay\\\" default=\\\"5\\\" \/&gt;\\n\\n  &lt;arg name=\\\"fragment_timeout\\\" default=\\\"600\\\" \/&gt;\\n  &lt;arg name=\\\"delay_between_messages\\\" default=\\\"0\\\" \/&gt;\\n  &lt;arg name=\\\"max_message_size\\\" default=\\\"None\\\" \/&gt;\\n\\n  &lt;arg name=\\\"authenticate\\\" default=\\\"false\\\" \/&gt;\\n\\n  &lt;group if=\\\"$(arg ssl)\\\"&gt;\\n    &lt;node name=\\\"rosbridge_websocket\\\" pkg=\\\"rosbridge_server\\\" type=\\\"rosbridge_websocket\\\" output=\\\"screen\\\"&gt;\\n      &lt;param name=\\\"certfile\\\" value=\\\"$(arg certfile)\\\" \/&gt;\\n      &lt;param name=\\\"keyfile\\\" value=\\\"$(arg keyfile)\\\" \/&gt;\\n      &lt;param name=\\\"authenticate\\\" value=\\\"$(arg authenticate)\\\" \/&gt;\\n      &lt;param name=\\\"port\\\" value=\\\"$(arg port)\\\"\/&gt;\\n      &lt;param name=\\\"address\\\" value=\\\"$(arg address)\\\"\/&gt;\\n      &lt;param name=\\\"retry_startup_delay\\\" value=\\\"$(arg retry_startup_delay)\\\"\/&gt;\\n      &lt;param name=\\\"fragment_timeout\\\" value=\\\"$(arg fragment_timeout)\\\"\/&gt;\\n      &lt;param name=\\\"delay_between_messages\\\" value=\\\"$(arg delay_between_messages)\\\"\/&gt;\\n      &lt;param name=\\\"max_message_size\\\" value=\\\"$(arg max_message_size)\\\"\/&gt;\\n    &lt;\/node&gt;\\n  &lt;\/group&gt;\\n  &lt;group unless=\\\"$(arg ssl)\\\"&gt;\\n    &lt;node name=\\\"rosbridge_websocket\\\" pkg=\\\"rosbridge_server\\\" type=\\\"rosbridge_websocket\\\" output=\\\"screen\\\"&gt;\\n      &lt;param name=\\\"authenticate\\\" value=\\\"$(arg authenticate)\\\" \/&gt;\\n      &lt;param name=\\\"port\\\" value=\\\"$(arg port)\\\"\/&gt;\\n      &lt;param name=\\\"address\\\" value=\\\"$(arg address)\\\"\/&gt;\\n      &lt;param name=\\\"retry_startup_delay\\\" value=\\\"$(arg retry_startup_delay)\\\"\/&gt;\\n      &lt;param name=\\\"fragment_timeout\\\" value=\\\"$(arg fragment_timeout)\\\"\/&gt;\\n      &lt;param name=\\\"delay_between_messages\\\" value=\\\"$(arg delay_between_messages)\\\"\/&gt;\\n      &lt;param name=\\\"max_message_size\\\" value=\\\"$(arg max_message_size)\\\"\/&gt;\\n    &lt;\/node&gt;\\n  &lt;\/group&gt;\\n\\n  &lt;node name=\\\"rosapi\\\" pkg=\\\"rosapi\\\" type=\\\"rosapi_node\\\" \/&gt;\\n\",\r\n        \"x\": 220,\r\n        \"y\": 160,\r\n        \"wires\": [\r\n            [\r\n                \"6c6e4866.b1c548\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"3e55c524.39868a\",\r\n        \"type\": \"inject\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"Start\",\r\n        \"topic\": \"\",\r\n        \"payload\": \"\",\r\n        \"payloadType\": \"date\",\r\n        \"repeat\": \"\",\r\n        \"crontab\": \"\",\r\n        \"once\": false,\r\n        \"x\": 110,\r\n        \"y\": 280,\r\n        \"wires\": [\r\n            [\r\n                \"403438bd.4561e8\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"4062327e.354b8c\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"content\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"payload\",\r\n        \"x\": 920,\r\n        \"y\": 200,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"6e3567b.42d3098\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"filename\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"filename\",\r\n        \"x\": 920,\r\n        \"y\": 140,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"e397f13b.7f1ea\",\r\n        \"type\": \"function\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"Convert Filename\",\r\n        \"func\": \"msg.filename = \\\"\/tmp\/\\\" + parseInt( new Date().getTime()) + \\\".launch\\\"\\nreturn msg;\",\r\n        \"outputs\": 1,\r\n        \"noerr\": 0,\r\n        \"x\": 450,\r\n        \"y\": 280,\r\n        \"wires\": [\r\n            [\r\n                \"29bdc1.1329624\",\r\n                \"6e3567b.42d3098\",\r\n                \"4062327e.354b8c\",\r\n                \"343cb1cc.66fa6e\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"29bdc1.1329624\",\r\n        \"type\": \"file\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"write launchfile\",\r\n        \"filename\": \"\",\r\n        \"appendNewline\": true,\r\n        \"createDir\": false,\r\n        \"overwriteFile\": \"false\",\r\n        \"x\": 720,\r\n        \"y\": 280,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"343cb1cc.66fa6e\",\r\n        \"type\": \"delay\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"Wait 1s\",\r\n        \"pauseType\": \"delay\",\r\n        \"timeout\": \"1\",\r\n        \"timeoutUnits\": \"seconds\",\r\n        \"rate\": \"1\",\r\n        \"nbRateUnits\": \"1\",\r\n        \"rateUnits\": \"second\",\r\n        \"randomFirst\": \"1\",\r\n        \"randomLast\": \"5\",\r\n        \"randomUnits\": \"seconds\",\r\n        \"drop\": false,\r\n        \"x\": 240,\r\n        \"y\": 400,\r\n        \"wires\": [\r\n            [\r\n                \"569f5f6e.3d6b4\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"3f9b0113.e9a65e\",\r\n        \"type\": \"exec\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"command\": \"roslaunch \",\r\n        \"addpay\": true,\r\n        \"append\": \"\",\r\n        \"useSpawn\": \"\",\r\n        \"timer\": \"\",\r\n        \"name\": \"\",\r\n        \"x\": 560,\r\n        \"y\": 400,\r\n        \"wires\": [\r\n            [\r\n                \"81ca8c0d.05b86\"\r\n            ],\r\n            [\r\n                \"380f8a22.6be1e6\"\r\n            ],\r\n            [\r\n                \"c640c322.33cef\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"81ca8c0d.05b86\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"stdout\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"payload\",\r\n        \"x\": 910,\r\n        \"y\": 340,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"380f8a22.6be1e6\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"stderr\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"payload\",\r\n        \"x\": 910,\r\n        \"y\": 380,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"c640c322.33cef\",\r\n        \"type\": \"debug\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"return code\",\r\n        \"active\": true,\r\n        \"console\": \"false\",\r\n        \"complete\": \"payload\",\r\n        \"x\": 930,\r\n        \"y\": 420,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"569f5f6e.3d6b4\",\r\n        \"type\": \"change\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"Set Launchfile\",\r\n        \"rules\": [\r\n            {\r\n                \"t\": \"set\",\r\n                \"p\": \"payload\",\r\n                \"pt\": \"msg\",\r\n                \"to\": \"filename\",\r\n                \"tot\": \"msg\"\r\n            }\r\n        ],\r\n        \"action\": \"\",\r\n        \"property\": \"\",\r\n        \"from\": \"\",\r\n        \"to\": \"\",\r\n        \"reg\": false,\r\n        \"x\": 400,\r\n        \"y\": 400,\r\n        \"wires\": [\r\n            [\r\n                \"3f9b0113.e9a65e\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"403438bd.4561e8\",\r\n        \"type\": \"template\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"&lt;launch&gt;\",\r\n        \"field\": \"payload\",\r\n        \"fieldType\": \"msg\",\r\n        \"format\": \"handlebars\",\r\n        \"syntax\": \"mustache\",\r\n        \"template\": \"&lt;launch&gt;\",\r\n        \"x\": 160,\r\n        \"y\": 120,\r\n        \"wires\": [\r\n            [\r\n                \"b73657b6.347178\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"6dcca7f7.5305c8\",\r\n        \"type\": \"template\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"&lt;\/launch&gt;\",\r\n        \"field\": \"payload\",\r\n        \"fieldType\": \"msg\",\r\n        \"format\": \"handlebars\",\r\n        \"syntax\": \"mustache\",\r\n        \"template\": \"{{&amp;payload}}&lt;\/launch&gt;\",\r\n        \"x\": 320,\r\n        \"y\": 240,\r\n        \"wires\": [\r\n            [\r\n                \"e397f13b.7f1ea\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"6c6e4866.b1c548\",\r\n        \"type\": \"template\",\r\n        \"z\": \"cc9a367a.dd0918\",\r\n        \"name\": \"3Dsensor.launch\",\r\n        \"field\": \"payload\",\r\n        \"fieldType\": \"msg\",\r\n        \"format\": \"html\",\r\n        \"syntax\": \"mustache\",\r\n        \"template\": \"{{&amp;payload}}  \\n  &lt;!-- 3D sensor --&gt;\\n  &lt;include file=\\\"$(find turtlebot_bringup)\/launch\/3dsensor.launch\\\"&gt;\\n    &lt;arg name=\\\"rgb_processing\\\" value=\\\"true\\\" \/&gt;\\n    &lt;arg name=\\\"depth_registration\\\" value=\\\"false\\\" \/&gt;\\n    &lt;arg name=\\\"depth_processing\\\" value=\\\"false\\\" \/&gt;\\n    \\n    &lt;!-- We must specify an absolute topic name because if not it will be prefixed by \\\"$(arg camera)\\\".\\n         Probably is a bug in the nodelet manager: https:\/\/github.com\/ros\/nodelet_core\/issues\/7 --&gt; \\n    &lt;arg name=\\\"scan_topic\\\" value=\\\"\/scan\\\" \/&gt;\\n  &lt;\/include&gt;\",\r\n        \"x\": 290,\r\n        \"y\": 200,\r\n        \"wires\": [\r\n            [\r\n                \"6dcca7f7.5305c8\"\r\n            ]\r\n        ]\r\n    }\r\n]<\/pre>\n<\/div>\n<p>That&#8217;s it! Happy hacking \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"mh-excerpt\"><p>Once you start using ROS you will have to write launch files that combine a set of ROS nodes to a meaningful robot runtime configuration. <a class=\"mh-excerpt-more\" href=\"https:\/\/marvinferber.net\/?p=75\" title=\"ROS and Node-RED Part 3: Managing ROS launch configurations\">[&#8230;]<\/a><\/p>\n<\/div>","protected":false},"author":1,"featured_media":105,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,2,4],"tags":[],"class_list":["post-75","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-nodered","category-ros","category-turtlebot"],"jetpack_featured_media_url":"https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-13-212703-e1492111715928.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/posts\/75","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/marvinferber.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=75"}],"version-history":[{"count":20,"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/posts\/75\/revisions"}],"predecessor-version":[{"id":102,"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/posts\/75\/revisions\/102"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/media\/105"}],"wp:attachment":[{"href":"https:\/\/marvinferber.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=75"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marvinferber.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=75"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marvinferber.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=75"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}