{"id":59,"date":"2017-04-08T21:07:30","date_gmt":"2017-04-08T20:07:30","guid":{"rendered":"http:\/\/marvinferber.net\/?p=59"},"modified":"2017-04-09T20:42:56","modified_gmt":"2017-04-09T19:42:56","slug":"ros-and-node-red-part-2-publishing-drive-commands","status":"publish","type":"post","link":"https:\/\/marvinferber.net\/?p=59","title":{"rendered":"ROS and Node-RED Part 2: Publishing drive commands"},"content":{"rendered":"<p>In this second tutorial, we are going to learn how to publish drive commands the a ROS robot from Node-RED. To do so, we need to use the publish node from the node-red-contrib-ros nodes. Unfortunately, the original is not supporting drive messages at the moment, I <a href=\"https:\/\/github.com\/marvinferber\/node-red-contrib-ros\">forked that repo<\/a> and modified the code on some lines. In order to use my forked repo, we need to reinstall node-red-contrib-ros from my Github space. I assume you have installed the software as shown in the preceding tutorial at this point. Do update the software as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">cd ~\/.node-red\r\nnpm uninstall node-red-contrib-ros\r\nnpm install git+https:\/\/github.com\/marvinferber\/node-red-contrib-ros<\/pre>\n<h2>Using the publish node<\/h2>\n<p>Now lets move back to the flow and set up the ROS publish node. If not done already, start Node-RED. We first need a new publish node and connect it to the ROS master that was configured in the preceding tutorial. As you might know as a ROS user, drive commands are published to \/cmd_vel_mux\/input\/teleop using a data object of type geometry_msgs\/Twist. Such a message consists of velocity commands for linear and radial velocities.<img loading=\"lazy\" decoding=\"async\" class=\" wp-image-65 aligncenter\" src=\"http:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-210113-e1491680810221.png\" alt=\"\" width=\"601\" height=\"275\" srcset=\"https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-210113-e1491680810221.png 796w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-210113-e1491680810221-300x137.png 300w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-210113-e1491680810221-768x351.png 768w\" sizes=\"auto, (max-width: 601px) 100vw, 601px\" \/><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">geometry_msgs\/Vector3 linear\r\n  float64 x\r\n  float64 y\r\n  float64 z\r\ngeometry_msgs\/Vector3 angular\r\n  float64 x\r\n  float64 y\r\n  float64 z<\/pre>\n<p>In Node-RED, we need to prepare a message with exactly the properties shown above using a function node for instance. Setting this message object of type geometry_msgs\/Twist as msg.payload, we are now able to publish drive commands.<img loading=\"lazy\" decoding=\"async\" class=\"wp-image-66 aligncenter\" src=\"http:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-210503-e1491680847266.png\" alt=\"\" width=\"934\" height=\"361\" srcset=\"https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-210503-e1491680847266.png 1252w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-210503-e1491680847266-300x116.png 300w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-210503-e1491680847266-768x297.png 768w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-210503-e1491680847266-1024x396.png 1024w\" sizes=\"auto, (max-width: 934px) 100vw, 934px\" \/><\/p>\n<h2>Publish messages in a loop<\/h2>\n<p>The last hurdle to make the robot actually move is to publish the drive commands in a constant loop at around 10-20Hz. There are many ways to implement a loop that publishes drive commands in Node-RED. You can implement a while loop following <a href=\"https:\/\/www.linkedin.com\/pulse\/node-red-design-patterns-stephen-keep\">this blog<\/a> post by a while pattern based on simple nodes only. Using simple nodes only, you can simply insert a delay node in your loop to slow down processing to a specific rate while keeping the event loop in Node-RED unstressed.<\/p>\n<p>Another approach would be to use a function node and publish messages from within a Javascript loop. In this case, be care not to block the event loop using any type of busy waiting. See<a href=\"http:\/\/stackoverflow.com\/questions\/13448374\/how-to-sleep-the-thread-in-node-js-without-affecting-other-threads\"> this post<\/a> for an explanation. I used a recursive program to achieve a non-blocking loop as shown below.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-69 aligncenter\" src=\"http:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-215131-e1491681261531.png\" alt=\"\" width=\"1009\" height=\"387\" srcset=\"https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-215131-e1491681261531.png 1252w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-215131-e1491681261531-300x115.png 300w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-215131-e1491681261531-768x294.png 768w, https:\/\/marvinferber.net\/wp-content\/uploads\/2017\/04\/Screenshot-at-2017-04-08-215131-e1491681261531-1024x393.png 1024w\" sizes=\"auto, (max-width: 1009px) 100vw, 1009px\" \/><\/p>\n<h2>Simulator users welcome<\/h2>\n<p>Again, this tutorial works perfectly fine for a simulated robot too. Be careful using drive commands on a real robot. We did not set up any safety mechanisms in this tutorial such as bumper stop or cliff detection.You can import the following flow into your Node-RED and try out the different possibilities of publishing drive commands. Start the process by injecting a single message or by starting the for loop to publish a sequence of messages.<\/p>\n<div style=\"overflow: auto; max-height: 600px;\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">[\r\n    {\r\n        \"id\": \"b3b3ae01.82c708\",\r\n        \"type\": \"tab\",\r\n        \"label\": \"Flow 1\"\r\n    },\r\n    {\r\n        \"id\": \"1edf948e.06392b\",\r\n        \"type\": \"ros-publish\",\r\n        \"z\": \"b3b3ae01.82c708\",\r\n        \"server\": \"f50f6311.80b15\",\r\n        \"topicname\": \"\/cmd_vel_mux\/input\/teleop\",\r\n        \"msgtype\": \"geometry_msgs\/Twist\",\r\n        \"x\": 758.5,\r\n        \"y\": 218,\r\n        \"wires\": []\r\n    },\r\n    {\r\n        \"id\": \"1469c2ad.5ecf8d\",\r\n        \"type\": \"function\",\r\n        \"z\": \"b3b3ae01.82c708\",\r\n        \"name\": \"set geometry_msg\/Twist\",\r\n        \"func\": \"\\nvar twist = {\\nlinear : {\\n  x : 0.1,\\n  y : 0.0,\\n  z : 0.0\\n},\\nangular : {\\n  x : 0.0,\\n  y : 0.0,\\n  z : 0.0\\n}\\n};\\nmsg.payload = twist;\\nreturn msg;\",\r\n        \"outputs\": 1,\r\n        \"noerr\": 0,\r\n        \"x\": 508.5,\r\n        \"y\": 219,\r\n        \"wires\": [\r\n            [\r\n                \"1edf948e.06392b\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"fc72bc5c.ccea3\",\r\n        \"type\": \"inject\",\r\n        \"z\": \"b3b3ae01.82c708\",\r\n        \"name\": \"inject a message\",\r\n        \"topic\": \"\",\r\n        \"payload\": \"\",\r\n        \"payloadType\": \"date\",\r\n        \"repeat\": \"\",\r\n        \"crontab\": \"\",\r\n        \"once\": false,\r\n        \"x\": 247.5,\r\n        \"y\": 219,\r\n        \"wires\": [\r\n            [\r\n                \"1469c2ad.5ecf8d\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"f7e9cf01.9776a\",\r\n        \"type\": \"inject\",\r\n        \"z\": \"b3b3ae01.82c708\",\r\n        \"name\": \"inject a sequence\",\r\n        \"topic\": \"\",\r\n        \"payload\": \"\",\r\n        \"payloadType\": \"date\",\r\n        \"repeat\": \"\",\r\n        \"crontab\": \"\",\r\n        \"once\": false,\r\n        \"x\": 258.5,\r\n        \"y\": 118,\r\n        \"wires\": [\r\n            [\r\n                \"138cb7e5.f57e2\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"138cb7e5.f57e2\",\r\n        \"type\": \"function\",\r\n        \"z\": \"b3b3ae01.82c708\",\r\n        \"name\": \"for loop\",\r\n        \"func\": \"var i = 0;\\nvar threshold = 20;\\nvar delay = 100;\\n\\nfunction recursive(){\\n    if (i &gt; threshold - 1)return;\\n    else{\\n        i++;\\n        msg.payload = i;\\n        node.send(msg);\\n        setTimeout(recursive, delay);\\n    }\\n}\\nsetTimeout(recursive, delay);\\n\\n\\n\",\r\n        \"outputs\": 1,\r\n        \"noerr\": 0,\r\n        \"x\": 446.5,\r\n        \"y\": 118,\r\n        \"wires\": [\r\n            [\r\n                \"1469c2ad.5ecf8d\"\r\n            ]\r\n        ]\r\n    },\r\n    {\r\n        \"id\": \"f50f6311.80b15\",\r\n        \"type\": \"ros-server\",\r\n        \"z\": \"\",\r\n        \"url\": \"ws:\/\/127.0.0.1:9090\/\"\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>In this second tutorial, we are going to learn how to publish drive commands the a ROS robot from Node-RED. To do so, we need <a class=\"mh-excerpt-more\" href=\"https:\/\/marvinferber.net\/?p=59\" title=\"ROS and Node-RED Part 2: Publishing drive commands\">[&#8230;]<\/a><\/p>\n<\/div>","protected":false},"author":1,"featured_media":67,"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-59","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-08-213025-e1491680873927.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/posts\/59","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=59"}],"version-history":[{"count":10,"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/posts\/59\/revisions"}],"predecessor-version":[{"id":86,"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/posts\/59\/revisions\/86"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/marvinferber.net\/index.php?rest_route=\/wp\/v2\/media\/67"}],"wp:attachment":[{"href":"https:\/\/marvinferber.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=59"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marvinferber.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=59"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marvinferber.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=59"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}