{"id":52,"date":"2017-02-07T06:40:15","date_gmt":"2017-02-07T11:40:15","guid":{"rendered":"http:\/\/commons.trincoll.edu\/trinityrobotics\/?p=52"},"modified":"2017-02-07T15:32:40","modified_gmt":"2017-02-07T20:32:40","slug":"callbacks-and-synchronicity-week-3","status":"publish","type":"post","link":"https:\/\/commons.trincoll.edu\/trinityrobotics\/callbacks-and-synchronicity-week-3\/","title":{"rendered":"Callbacks and Synchronicity &#8211; Week 3"},"content":{"rendered":"<p>Robotics and its software differ from a typical software in its two main requirements.<\/p>\n<p>The first requirement is that robot software must <strong>react differently\u00a0<\/strong>based on environmental changes and conditions &#8211; often modeled by a<strong> state machine<\/strong> and its states (see<a href=\"https:\/\/en.wikipedia.org\/wiki\/Finite-state_machine\"> here<\/a>, but at its simplest, it&#8217;s just if&#8217;s in a while loop).<\/p>\n<p>For example, should the robot not enter into a recovery state after ramming into some obstacle, rather than continuing to pummel through? Even if all the visuals and sensor\u00a0data may be the same, the robot must act differently in a recovery state than the\u00a0normal state.<\/p>\n<p>Another requirement is that the robot (the state machine above or something else) <strong>needs to be able to handle inputs and requests from multiple sources<\/strong> &#8211; from the sensor data, requested actions, and such. Here, the complexity emerges, and ROS is handed the duties of a typical operating system &#8211; managing multiple programs at once.<\/p>\n<p>ROS, in its distributed approach, does not have THE state machine, but rather leaves it to each node to determine its own state\u00a0and resolve the potential conflicts (an approach supported by recent neuroscience advances).<\/p>\n<p>So, when designing nodes for ROS, one must be aware of these requirements.<\/p>\n<p>But first of all, let us first discuss the\u00a0<strong>service\u00a0<\/strong>tool, which is a\u00a0<strong>synchronous way to establish one-to-one communication,<\/strong>\u00a0which means that there is an order to the communications.<strong>\u00a0<\/strong>The order is the following:\u00a0A node (client) would send a request to another node (server), possibly waiting for a reply as the server processes the request.<\/p>\n<p>Where in the code do the waiting and processing happen? The waiting happens at <code>spin() and spinOnce()<\/code>, while the processing happens in the callback.<\/p>\n<p>Each node, when they receive messages through topics or service, <strong>does not immediately process them<\/strong>, as they very well might be doing something more important. Instead, the messages are held in the queue (a line essentially) and processed as a batch during the\u00a0<code>spin()<\/code> commands.<\/p>\n<p>So what is the <a href=\"http:\/\/wiki.ros.org\/roscpp\/Overview\/Callbacks%20and%20Spinning\">difference <\/a>between\u00a0<code>spinOnce()<\/code> and\u00a0<code>spin()<\/code>?\u00a0<code>spin()<\/code> is essentially\u00a0<code>spinOnce()<\/code> called in a loop &#8211; once the node runs\u00a0<code>spin()<\/code>, the node will now only deal with the callbacks. By comparison,\u00a0<code>spinOnce()<\/code> allows the node to process the callbacks at the designated time &#8220;once&#8221;.<\/p>\n<p>So when should you use each? You should use\u00a0<code>spinOnce()<\/code> if you have a code not part of the callback that constantly needs to run and\u00a0<code>spin()<\/code> if the server only needs to deal with callbacks from then on. Also, with <code>spinOnce()<\/code>,\u00a0you need to be aware of the time that will take to process the tasks between\u00a0<code>spinOnce()<\/code>, making sure that the tasks will not prevent callback from activating too late.<\/p>\n<p>And for the services in general, you need to also consider the time that the service will take, making sure it doesn&#8217;t occupy the server for too long. Otherwise, the server will not be able to react quickly to the inputs from other nodes &#8211; perhaps a command that is requesting for the robot to freeze immediately. Thus, it is generally recommended that\u00a0<strong>services be simple, short requests.<\/strong><\/p>\n<p>However, you would need the ability to command a robot to do a more complicated task &#8211; or even allow for multitasking of tasks. For those requirements, there is the <a href=\"http:\/\/wiki.ros.org\/actionlib\/DetailedDescription\">action lib<\/a>. In contrast to service, it is &#8211; and must be &#8211;\u00a0<strong>an asynchronous way to communicate one-to-one.\u00a0<\/strong><\/p>\n<p>Why the must? The actions must be asynchronous, as for actions with a long-time frame (~seconds), the state of the robot might change, with <strong>actions needed to be interrupted and continued later.<\/strong>\u00a0So actions are asynchronous because the execution of action is <strong>not fixed<\/strong> &#8211; unlike services, which can&#8217;t be interrupted.<\/p>\n<p>While the exact details of both service and action is in the respective tutorials, these differing goals for services and actions must be accounted for when making servers (nodes) for each of them &#8211; asking if the service or action would be more appropriate at this point.<\/p>\n<p>Assignment: Implement a client\/service, in which client sends in a service to the server to change the state of the server in some way.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Robotics and its software differ from a typical software in its two main requirements. The first requirement is that robot software must react differently\u00a0based on environmental changes and conditions &#8211; often modeled by a state machine and its states (see here, but at its simplest, it&#8217;s just if&#8217;s in a while loop). For example, should &hellip; <a href=\"https:\/\/commons.trincoll.edu\/trinityrobotics\/callbacks-and-synchronicity-week-3\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Callbacks and Synchronicity &#8211; Week 3&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1933,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/posts\/52"}],"collection":[{"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/users\/1933"}],"replies":[{"embeddable":true,"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/comments?post=52"}],"version-history":[{"count":5,"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/posts\/52\/revisions"}],"predecessor-version":[{"id":58,"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/posts\/52\/revisions\/58"}],"wp:attachment":[{"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/media?parent=52"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/categories?post=52"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/commons.trincoll.edu\/trinityrobotics\/wp-json\/wp\/v2\/tags?post=52"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}