{"action":"created","comment":{"url":"https://api.github.com/repos/ros2/design/pulls/comments/39791105","id":39791105,"diff_hunk":"@@ -0,0 +1,176 @@\n+---\n+layout: default\n+title: Managed nodes\n+abstract:\n+  This article describes the concept of a node with a managed life cycle. It aims to document some of the options for supporting managed-life cycle nodes in ROS 2. It has been written with consideration for the existing design of the ROS 2 C++ client library, and in particular the current design of executors.\n+author: '[Geoffrey Biggs](https://github.com/gbiggs)'\n+published: true\n+---\n+\n+{:toc}\n+\n+# {{ page.title }}\n+\n+<div class=\"abstract\" markdown=\"1\">\n+{{ page.abstract }}\n+</div>\n+\n+Original Author: {{ page.author }}\n+\n+## Background\n+\n+A managed life cycle for nodes allows greater precision over the state of ROS system. It will allow roslaunch to have greater control over launching a ROS system, and in particular will allow roslaunch to ensure that all components have been instantiated correctly before it allows any component to begin executing its behaviour. It will also allow nodes to be restarted or replaced on-line.\n+\n+The most important concept of this document is that a managed node presents a known interface, executes according to a known life cycle state machine, and otherwise can be considered a black box. This allows freedom to the node developer on how they provide the managed life cycle functionality, while also ensuring that any tools created for managing nodes can work with any compliant node.\n+\n+\n+## Glossary\n+\n+* Configuration: To alter aspects of a node's behaviour through known interfaces (services and topics). This includes setting parameters and connecting topics. Configuration may be performed multiple times during a node's life.\n+* Initialise: To shift a node from the created state to the inactive state, during which the node is prepared for execution. For example, memory buffers can be allocated.\n+* Activate: To shift a node from the inactive state to the active state. For example, internal variables can be re-initialised based on changed configuration parameters and hardware access may be obtained.\n+* Deactivate: To shift a node from the active state to the inactive state. For example, hardware access may be relinquished.\n+* Fatal error: An unforeseen error that cannot be handled by the robot application, requiring the node to be reset or destroyed.\n+\n+\n+## Life cycle\n+\n+![The proposed node life cycle state machine](/img/node_lifecycle/life_cycle_sm.png \"The proposed node life cycle state machine\")\n+\n+The behaviour of each state is as defined below.\n+\n+### Created state\n+\n+This is the life cycle state the node is in immediately after being instantiated.\n+\n+The node may transition to the `inactive` state by being initialised. Initialisation of a node will typically involve those tasks that must be performed once during the node's life time, such as obtaining permanent memory buffers and setting up topic publications/subscriptions that do not change.\n+\n+Implementation note: In object-oriented languages, the onCreated method can be mapped to the class constructor.\n+\n+### Inactive state\n+\n+This state represents a node that is not currently performing any processing.\n+\n+The main purpose of this state is to allow a node to be (re-)configured (changing configuration parameters, adding and removing topic publications/subscriptions, etc.) without altering its behaviour while it is running.\n+\n+[To discuss: Should there be a callback for when configuration is changed, e.g. altered parameters, new topics, etc.?]\n+\n+While in this state, the node will not receive any execution time to read topics, perform processing of data, respond to functional service requests, etc.\n+\n+In the inactive state, any data that arrives on topics will not be read. Whether or not data is queued will depend on the QoS parameters of the topics involved. [In other words, to queue data or not is up to each topic.]\n+\n+Any service requests to a node in the inactive state will not be answered (to the caller, they will fail immediately).\n+\n+Entering the `inactive` state from the `created` state requires running the node's `onInitialised` method. The node uses this to set up any resources it must hold throughout its life (irrespective of if it is active or inactive). As examples, such resources may include topic publications and subscriptions, memory that is held continuously, and initialising configuration parameters.\n+\n+Entering the `inactive` state from the `active` state requires running the node's `onDeactivated` method. See the `active` state description for more information.\n+\n+Entering the `inactive` state from the `fatal error` state requires running the node's `onReset` method. See the `fatal error` state description for more information.\n+\n+If an error occurs while in this state that cannot be handled by the node, then the transition to the `fatal error` state is taken.\n+\n+The node may also exit this state by being destroyed, in which case the `destroy` transition is taken.\n+\n+Implementation note: Causing the transition to the destroyed state can often be mapped to deletion of the node instance.\n+\n+### Active state\n+\n+This is the main state of the node's life cycle. While in this state, the node performs any processing, responds to service requests, reads and processes data, produces output, etc.\n+\n+Entering the `active` state requires running the node's `onActivated` method. This is used to prepare the node for execution. This may include acquiring resources that are only held while the node is actually active, such as access to hardware. Ideally, no preparation that requires significant time (such as lengthy hardware initialisation) should be performed in this callback.\n+\n+To shut down a node, it must first be deactivated. This will cause the `onDeactivate` method to be called, allowing the node to clean up any resources it only holds while active.\n+\n+If an error that cannot be handled by the node/system occurs in this state, the transition to the `fatal error` state is taken.\n+\n+### Fatal Error state\n+\n+Known errors that can occur in a node should be considered designed behaviour of the system and so should be handled by the node where the error occurred and, if necessary, the surrounding nodes. The reason for this is that the system knows best how to handle errors that occur in its behaviour.\n+\n+Any fatal errors (those which the node/system was not expecting and does not know how to handle) will cause a transition to the `fatal error` state. In this state, because the node does not know what to do in the presence of the error, it is not provided any execution time. Arriving data is not processed, service requests are not responded to, and no output is produced.\n+\n+On entering the `fatal error` state, the node's `onError` method must be executed. This provides the node with a chance to clean up resources it was using.","path":"articles/node_lifecycle.md","position":92,"original_position":92,"commit_id":"db0e9fd7c3ebc3ab1cc535bdd582ac0c32400f7b","original_commit_id":"db0e9fd7c3ebc3ab1cc535bdd582ac0c32400f7b","user":{"login":"doudou","id":292,"avatar_url":"https://avatars.githubusercontent.com/u/292?v=3","gravatar_id":"","url":"https://api.github.com/users/doudou","html_url":"https://github.com/doudou","followers_url":"https://api.github.com/users/doudou/followers","following_url":"https://api.github.com/users/doudou/following{/other_user}","gists_url":"https://api.github.com/users/doudou/gists{/gist_id}","starred_url":"https://api.github.com/users/doudou/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/doudou/subscriptions","organizations_url":"https://api.github.com/users/doudou/orgs","repos_url":"https://api.github.com/users/doudou/repos","events_url":"https://api.github.com/users/doudou/events{/privacy}","received_events_url":"https://api.github.com/users/doudou/received_events","type":"User","site_admin":false},"body":"> I don't see where you mentioned \"fatal errors\" vs \"normal errors\" above, can you reiterate that or point it out directly?\r\n\r\nYeah, not very smart of me to not copy/paste the paragraph. I was referring to RTT's exception vs. fatal error state:\r\n\r\n~~~\r\nRTT has separated exception and fatal error states for this very purpose. exception is the state the component transitions to if there is a problem during any other transition/state, and transitioning to exception causes first a call to the deactivate/deconfigure handlers (if the component was resp. in activated/configured). Fatal error is what state the component ends up in if there is a problem while transitioning to exception. The only way to handle fatal error is to destroy the component (or, more accurately, kill the process as you really don't know in which \"state\" the actual code is)\r\n~~~\r\n\r\nBasically RTT's Exception is what is proposed as Fatal and Fatal Error does not exist.","created_at":"2015-09-17T19:55:58Z","updated_at":"2015-09-17T19:55:58Z","html_url":"https://github.com/ros2/design/pull/34#discussion_r39791105","pull_request_url":"https://api.github.com/repos/ros2/design/pulls/34","_links":{"self":{"href":"https://api.github.com/repos/ros2/design/pulls/comments/39791105"},"html":{"href":"https://github.com/ros2/design/pull/34#discussion_r39791105"},"pull_request":{"href":"https://api.github.com/repos/ros2/design/pulls/34"}}},"pull_request":{"url":"https://api.github.com/repos/ros2/design/pulls/34","id":38077891,"html_url":"https://github.com/ros2/design/pull/34","diff_url":"https://github.com/ros2/design/pull/34.diff","patch_url":"https://github.com/ros2/design/pull/34.patch","issue_url":"https://api.github.com/repos/ros2/design/issues/34","number":34,"state":"open","locked":false,"title":"Draft of article about node life cycle design","user":{"login":"gbiggs","id":163151,"avatar_url":"https://avatars.githubusercontent.com/u/163151?v=3","gravatar_id":"","url":"https://api.github.com/users/gbiggs","html_url":"https://github.com/gbiggs","followers_url":"https://api.github.com/users/gbiggs/followers","following_url":"https://api.github.com/users/gbiggs/following{/other_user}","gists_url":"https://api.github.com/users/gbiggs/gists{/gist_id}","starred_url":"https://api.github.com/users/gbiggs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gbiggs/subscriptions","organizations_url":"https://api.github.com/users/gbiggs/orgs","repos_url":"https://api.github.com/users/gbiggs/repos","events_url":"https://api.github.com/users/gbiggs/events{/privacy}","received_events_url":"https://api.github.com/users/gbiggs/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-06-19T05:27:46Z","updated_at":"2015-09-17T19:55:58Z","closed_at":null,"merged_at":null,"merge_commit_sha":"abbcb047868af01ed80da9e23fc2b1c29ad63f10","assignee":{"login":"tfoote","id":447804,"avatar_url":"https://avatars.githubusercontent.com/u/447804?v=3","gravatar_id":"","url":"https://api.github.com/users/tfoote","html_url":"https://github.com/tfoote","followers_url":"https://api.github.com/users/tfoote/followers","following_url":"https://api.github.com/users/tfoote/following{/other_user}","gists_url":"https://api.github.com/users/tfoote/gists{/gist_id}","starred_url":"https://api.github.com/users/tfoote/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tfoote/subscriptions","organizations_url":"https://api.github.com/users/tfoote/orgs","repos_url":"https://api.github.com/users/tfoote/repos","events_url":"https://api.github.com/users/tfoote/events{/privacy}","received_events_url":"https://api.github.com/users/tfoote/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/ros2/design/pulls/34/commits","review_comments_url":"https://api.github.com/repos/ros2/design/pulls/34/comments","review_comment_url":"https://api.github.com/repos/ros2/design/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ros2/design/issues/34/comments","statuses_url":"https://api.github.com/repos/ros2/design/statuses/db0e9fd7c3ebc3ab1cc535bdd582ac0c32400f7b","head":{"label":"gbiggs:gh-pages","ref":"gh-pages","sha":"db0e9fd7c3ebc3ab1cc535bdd582ac0c32400f7b","user":{"login":"gbiggs","id":163151,"avatar_url":"https://avatars.githubusercontent.com/u/163151?v=3","gravatar_id":"","url":"https://api.github.com/users/gbiggs","html_url":"https://github.com/gbiggs","followers_url":"https://api.github.com/users/gbiggs/followers","following_url":"https://api.github.com/users/gbiggs/following{/other_user}","gists_url":"https://api.github.com/users/gbiggs/gists{/gist_id}","starred_url":"https://api.github.com/users/gbiggs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gbiggs/subscriptions","organizations_url":"https://api.github.com/users/gbiggs/orgs","repos_url":"https://api.github.com/users/gbiggs/repos","events_url":"https://api.github.com/users/gbiggs/events{/privacy}","received_events_url":"https://api.github.com/users/gbiggs/received_events","type":"User","site_admin":false},"repo":{"id":37644874,"name":"design","full_name":"gbiggs/design","owner":{"login":"gbiggs","id":163151,"avatar_url":"https://avatars.githubusercontent.com/u/163151?v=3","gravatar_id":"","url":"https://api.github.com/users/gbiggs","html_url":"https://github.com/gbiggs","followers_url":"https://api.github.com/users/gbiggs/followers","following_url":"https://api.github.com/users/gbiggs/following{/other_user}","gists_url":"https://api.github.com/users/gbiggs/gists{/gist_id}","starred_url":"https://api.github.com/users/gbiggs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gbiggs/subscriptions","organizations_url":"https://api.github.com/users/gbiggs/orgs","repos_url":"https://api.github.com/users/gbiggs/repos","events_url":"https://api.github.com/users/gbiggs/events{/privacy}","received_events_url":"https://api.github.com/users/gbiggs/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/gbiggs/design","description":"Design documentation for ROS 2.0 effort","fork":true,"url":"https://api.github.com/repos/gbiggs/design","forks_url":"https://api.github.com/repos/gbiggs/design/forks","keys_url":"https://api.github.com/repos/gbiggs/design/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gbiggs/design/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gbiggs/design/teams","hooks_url":"https://api.github.com/repos/gbiggs/design/hooks","issue_events_url":"https://api.github.com/repos/gbiggs/design/issues/events{/number}","events_url":"https://api.github.com/repos/gbiggs/design/events","assignees_url":"https://api.github.com/repos/gbiggs/design/assignees{/user}","branches_url":"https://api.github.com/repos/gbiggs/design/branches{/branch}","tags_url":"https://api.github.com/repos/gbiggs/design/tags","blobs_url":"https://api.github.com/repos/gbiggs/design/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gbiggs/design/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gbiggs/design/git/refs{/sha}","trees_url":"https://api.github.com/repos/gbiggs/design/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gbiggs/design/statuses/{sha}","languages_url":"https://api.github.com/repos/gbiggs/design/languages","stargazers_url":"https://api.github.com/repos/gbiggs/design/stargazers","contributors_url":"https://api.github.com/repos/gbiggs/design/contributors","subscribers_url":"https://api.github.com/repos/gbiggs/design/subscribers","subscription_url":"https://api.github.com/repos/gbiggs/design/subscription","commits_url":"https://api.github.com/repos/gbiggs/design/commits{/sha}","git_commits_url":"https://api.github.com/repos/gbiggs/design/git/commits{/sha}","comments_url":"https://api.github.com/repos/gbiggs/design/comments{/number}","issue_comment_url":"https://api.github.com/repos/gbiggs/design/issues/comments{/number}","contents_url":"https://api.github.com/repos/gbiggs/design/contents/{+path}","compare_url":"https://api.github.com/repos/gbiggs/design/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gbiggs/design/merges","archive_url":"https://api.github.com/repos/gbiggs/design/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gbiggs/design/downloads","issues_url":"https://api.github.com/repos/gbiggs/design/issues{/number}","pulls_url":"https://api.github.com/repos/gbiggs/design/pulls{/number}","milestones_url":"https://api.github.com/repos/gbiggs/design/milestones{/number}","notifications_url":"https://api.github.com/repos/gbiggs/design/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gbiggs/design/labels{/name}","releases_url":"https://api.github.com/repos/gbiggs/design/releases{/id}","created_at":"2015-06-18T07:35:50Z","updated_at":"2015-06-18T07:35:51Z","pushed_at":"2015-09-02T05:30:21Z","git_url":"git://github.com/gbiggs/design.git","ssh_url":"git@github.com:gbiggs/design.git","clone_url":"https://github.com/gbiggs/design.git","svn_url":"https://github.com/gbiggs/design","homepage":"http://design.ros2.org/","size":900,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"gh-pages"}},"base":{"label":"ros2:gh-pages","ref":"gh-pages","sha":"ba9fe29cdf13497f01eaf72b613bf01c3754d90c","user":{"login":"ros2","id":3979232,"avatar_url":"https://avatars.githubusercontent.com/u/3979232?v=3","gravatar_id":"","url":"https://api.github.com/users/ros2","html_url":"https://github.com/ros2","followers_url":"https://api.github.com/users/ros2/followers","following_url":"https://api.github.com/users/ros2/following{/other_user}","gists_url":"https://api.github.com/users/ros2/gists{/gist_id}","starred_url":"https://api.github.com/users/ros2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ros2/subscriptions","organizations_url":"https://api.github.com/users/ros2/orgs","repos_url":"https://api.github.com/users/ros2/repos","events_url":"https://api.github.com/users/ros2/events{/privacy}","received_events_url":"https://api.github.com/users/ros2/received_events","type":"Organization","site_admin":false},"repo":{"id":14241623,"name":"design","full_name":"ros2/design","owner":{"login":"ros2","id":3979232,"avatar_url":"https://avatars.githubusercontent.com/u/3979232?v=3","gravatar_id":"","url":"https://api.github.com/users/ros2","html_url":"https://github.com/ros2","followers_url":"https://api.github.com/users/ros2/followers","following_url":"https://api.github.com/users/ros2/following{/other_user}","gists_url":"https://api.github.com/users/ros2/gists{/gist_id}","starred_url":"https://api.github.com/users/ros2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ros2/subscriptions","organizations_url":"https://api.github.com/users/ros2/orgs","repos_url":"https://api.github.com/users/ros2/repos","events_url":"https://api.github.com/users/ros2/events{/privacy}","received_events_url":"https://api.github.com/users/ros2/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ros2/design","description":"Design documentation for ROS 2.0 effort","fork":false,"url":"https://api.github.com/repos/ros2/design","forks_url":"https://api.github.com/repos/ros2/design/forks","keys_url":"https://api.github.com/repos/ros2/design/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ros2/design/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ros2/design/teams","hooks_url":"https://api.github.com/repos/ros2/design/hooks","issue_events_url":"https://api.github.com/repos/ros2/design/issues/events{/number}","events_url":"https://api.github.com/repos/ros2/design/events","assignees_url":"https://api.github.com/repos/ros2/design/assignees{/user}","branches_url":"https://api.github.com/repos/ros2/design/branches{/branch}","tags_url":"https://api.github.com/repos/ros2/design/tags","blobs_url":"https://api.github.com/repos/ros2/design/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ros2/design/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ros2/design/git/refs{/sha}","trees_url":"https://api.github.com/repos/ros2/design/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ros2/design/statuses/{sha}","languages_url":"https://api.github.com/repos/ros2/design/languages","stargazers_url":"https://api.github.com/repos/ros2/design/stargazers","contributors_url":"https://api.github.com/repos/ros2/design/contributors","subscribers_url":"https://api.github.com/repos/ros2/design/subscribers","subscription_url":"https://api.github.com/repos/ros2/design/subscription","commits_url":"https://api.github.com/repos/ros2/design/commits{/sha}","git_commits_url":"https://api.github.com/repos/ros2/design/git/commits{/sha}","comments_url":"https://api.github.com/repos/ros2/design/comments{/number}","issue_comment_url":"https://api.github.com/repos/ros2/design/issues/comments{/number}","contents_url":"https://api.github.com/repos/ros2/design/contents/{+path}","compare_url":"https://api.github.com/repos/ros2/design/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ros2/design/merges","archive_url":"https://api.github.com/repos/ros2/design/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ros2/design/downloads","issues_url":"https://api.github.com/repos/ros2/design/issues{/number}","pulls_url":"https://api.github.com/repos/ros2/design/pulls{/number}","milestones_url":"https://api.github.com/repos/ros2/design/milestones{/number}","notifications_url":"https://api.github.com/repos/ros2/design/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ros2/design/labels{/name}","releases_url":"https://api.github.com/repos/ros2/design/releases{/id}","created_at":"2013-11-08T18:56:29Z","updated_at":"2015-09-11T19:47:48Z","pushed_at":"2015-09-16T01:23:31Z","git_url":"git://github.com/ros2/design.git","ssh_url":"git@github.com:ros2/design.git","clone_url":"https://github.com/ros2/design.git","svn_url":"https://github.com/ros2/design","homepage":"http://design.ros2.org/","size":1845,"stargazers_count":18,"watchers_count":18,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":22,"mirror_url":null,"open_issues_count":12,"forks":22,"open_issues":12,"watchers":18,"default_branch":"gh-pages"}},"_links":{"self":{"href":"https://api.github.com/repos/ros2/design/pulls/34"},"html":{"href":"https://github.com/ros2/design/pull/34"},"issue":{"href":"https://api.github.com/repos/ros2/design/issues/34"},"comments":{"href":"https://api.github.com/repos/ros2/design/issues/34/comments"},"review_comments":{"href":"https://api.github.com/repos/ros2/design/pulls/34/comments"},"review_comment":{"href":"https://api.github.com/repos/ros2/design/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ros2/design/pulls/34/commits"},"statuses":{"href":"https://api.github.com/repos/ros2/design/statuses/db0e9fd7c3ebc3ab1cc535bdd582ac0c32400f7b"}}}}