Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actions proposal #193

Merged
merged 76 commits into from
Mar 14, 2019
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
104df38
Add original proposal
gbiggs Aug 1, 2018
cc48341
Reformat and revise some of the information
gbiggs Aug 1, 2018
b3edf0a
Fix missing close preformat
gbiggs Aug 1, 2018
ded103a
Merge branch 'gh-pages' of https://github.com/gbiggs/design into acti…
sloretz Oct 10, 2018
29e0280
ROS 2 action server always generates goal id
sloretz Oct 10, 2018
cfe4e66
Rough description of services and topics
sloretz Oct 10, 2018
c00f875
ROS 1 cancels goals with stamps less than or equal to given time
sloretz Oct 10, 2018
68320a4
Add API section for action server
jacobperron Oct 10, 2018
85dba7d
Actions implemented in rcl
sloretz Oct 10, 2018
d3dc0be
Merge branch 'actions_proposal' of github.com:ros2/design into action…
sloretz Oct 10, 2018
da638a9
More italics
sloretz Oct 10, 2018
45a7d0b
QoS warning for goal submission service
sloretz Oct 10, 2018
b263fd3
Add API section for action client
jacobperron Oct 10, 2018
508247f
call -> calls
sloretz Oct 10, 2018
98d2ba5
Server discards result after giving it to the client
sloretz Oct 10, 2018
7782276
Actions namespaced separately from msg and srv definitions
sloretz Oct 10, 2018
23e942b
Shrink possible statuses
sloretz Oct 10, 2018
4efd85e
Replace high-level API section with details about goal states
jacobperron Oct 10, 2018
0d83eb8
Begin section about bridging ROS 1 and ROS 2
sloretz Oct 10, 2018
8b97ce8
Add Action Server C++ examples
jacobperron Oct 11, 2018
2c7e9e3
Move SimpleActionServer example to separate section
jacobperron Oct 11, 2018
2fb606c
Add include and type alias to action server example
jacobperron Oct 11, 2018
95f6ad3
Add Action Client C++ examples
jacobperron Oct 11, 2018
8d9ccbf
Bridge R1 client and R2 server expanded
sloretz Oct 11, 2018
d70f38f
Merge branch 'actions_proposal' of github.com:ros2/design into action…
sloretz Oct 11, 2018
1a5d958
Move API examples to examples repo
jacobperron Oct 11, 2018
bde9d09
Rough start to bridging ROS 1 server and ROS 2 client
sloretz Oct 11, 2018
224f081
Merge branch 'actions_proposal' of github.com:ros2/design into action…
sloretz Oct 11, 2018
d634a61
Update goal state machine
jacobperron Oct 11, 2018
4c856b2
Move bridge to bottom
sloretz Oct 11, 2018
244c3f4
Link to python actions api
sloretz Oct 11, 2018
63530b5
minor grammar
jacobperron Oct 11, 2018
08c106b
Update background
jacobperron Oct 11, 2018
d92fcce
Move Goal identifier section and add more rationale
sloretz Oct 11, 2018
8076d96
Minor wording in goal subscription service section
sloretz Oct 11, 2018
5a9ccd0
Simplify explanation of why actions aren't in rmw
sloretz Oct 11, 2018
9ed5359
Reword goalid sentences
sloretz Oct 11, 2018
0172831
Stub alternatives section
sloretz Oct 12, 2018
ad1dd1f
Start section of ROS 1 vs ROS 2 and move stuff to it
sloretz Oct 12, 2018
70b5f8e
Delete content in bridge section
sloretz Oct 12, 2018
8abbb23
Remove realtime section stub
sloretz Oct 12, 2018
69e36b7
Services promoted to 1 section type higher
sloretz Oct 12, 2018
1cce6b6
Move rmw note to alternatives section
sloretz Oct 12, 2018
2c104af
More content in differences section
sloretz Oct 12, 2018
d71f0d1
move differences higher up
sloretz Oct 12, 2018
53c0e3c
specification -> Interface Definition
sloretz Oct 12, 2018
0f587c0
Add goal lifecycle examples
jacobperron Oct 12, 2018
e12ab46
Note about visibility of topics and services
sloretz Oct 12, 2018
72894ea
Shorten abstract
sloretz Oct 12, 2018
5e6af9c
Rename 'goal lifecycle' examples to 'interaction' examples
jacobperron Oct 12, 2018
3404684
Shorten introduction section
sloretz Oct 12, 2018
9ecd148
Merge branch 'actions_proposal' of github.com:ros2/design into action…
sloretz Oct 12, 2018
d6f7333
Shorten sentence
sloretz Oct 12, 2018
e24800a
Minor rewording at start
sloretz Oct 12, 2018
d7323ec
Reword/reformat section about entities involved in an action
sloretz Oct 12, 2018
206f6be
Make fragments in Action Inteface Definition complete sentences
sloretz Oct 12, 2018
86b2e30
Introdice state machine before diagram
sloretz Oct 12, 2018
94b9306
move introspection tools section higher
sloretz Oct 12, 2018
9706472
Slight formating chnages to introspection tools section
sloretz Oct 12, 2018
8187434
Status topic is a list
sloretz Oct 12, 2018
1e7e6bb
grammar requires ;
sloretz Oct 12, 2018
daa529e
1 sentece becomes 2
sloretz Oct 12, 2018
5de40c7
Add actions interaction overview diagram
jacobperron Oct 12, 2018
887ad87
Update goal state machine
jacobperron Oct 16, 2018
afaf5f3
Fix typos and grammer, consistency in lingo, and let action clients g…
jacobperron Oct 16, 2018
7b5144e
Add a couple sentences regarding QoS for action feedback and status t…
jacobperron Oct 16, 2018
77216b1
Add section about using multiple topics for feedback/status in 'Alter…
jacobperron Oct 16, 2018
a6144c7
Fix logic in cancel policy
jacobperron Oct 18, 2018
ad1b326
Minor clarifications
jacobperron Oct 31, 2018
a439740
Add topic and service name generation
sloretz Nov 1, 2018
1ff406d
Address feedback from review
jacobperron Feb 13, 2019
b7ac32a
Add sub-section to alternavtives on action server goal ID generation
jacobperron Feb 14, 2019
0baa626
Update interaction example diagram
jacobperron Feb 14, 2019
d72d100
Fix author line
jacobperron Feb 14, 2019
1c98b9b
Add third action interfaction example
jacobperron Feb 14, 2019
f4b59fa
Fix typos, broken link, and rename goal events
jacobperron Mar 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
338 changes: 338 additions & 0 deletions articles/actions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,338 @@
---
layout: default
title: Actions
permalink: articles/actions.html
abstract:
Actions are one of the three core types of interaction between ROS nodes.
This article specifies the requirements for actions, how they've changed from ROS 1, and how they're communicated.
author: '[Geoffrey Biggs](https://github.com/gbiggs)'
jacobperron marked this conversation as resolved.
Show resolved Hide resolved
published: true
---

{:toc}

# {{ page.title }}

<div class="abstract" markdown="1">
{{ page.abstract }}
</div>

Original Author: {{ page.author }}

## Background

There are three forms of communication in ROS: topics, services, and actions.
Topic publishers broadcast to multiple subscribers, but communication is one-way.
Service clients send a request to a service server and get a response, but there is no information about the progress.
Similar to services, actions clients ask an action server reach some end state and will get a response.
Unlike services, while the action is being peformed the action server sends progress updates to the client.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps change "progress updates" to "progress feedback" to be more consistent with the naming of things below.


Actions are useful when a response may take a significant length of time.
They allow a client to track the progress of a request, get the final outcome, and optionally cancel the request it before it completes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after "cancel the request" there probably shouldn't be an "it"


This document defines requirements for actions, how they are specified in the ROS Message IDL, and how they are communicated by the middleware.

## Entities Involved in Actions

There are two entities involved in actions: an action server and an action client.

### Action Server

An action server provides an action.
Like topics and services, an action server has a name and a type.
There is only one server per name.
sloretz marked this conversation as resolved.
Show resolved Hide resolved

It is responsible for

* advertising the action to other ROS entities
* accepting or rejecting requests from one or more action clients
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, we may consider using the term "goal" here (and elsewhere in the doc) when referring to requests from action clients.

* executing the action when a request is received and accepted
* optionally providing feedback about the progress of all executing actions
sloretz marked this conversation as resolved.
Show resolved Hide resolved
* optionally handling requests to cancel an action
* sending the result of the action, including whether it succeed, failed, or was cancelled, to the client when the action completes

### Action Client

An action client requests an action to be performed and monitors its progress.
There may be multiple clients per server; however, it is up to the server to decide how requests from multiple clients will be handled.

It is responsible for

* making a request to the action server
* optionally monitoring the feedback from the action server
* optionally requesting that the action server cancel the action execution
* optionally checking the result of the action received from the action server

## Differences between ROS 1 and ROS 2 actions

### First Class Support
In ROS 1, actions are implemented as a separate library `actionlib` which is built on top of the client libraries.
This was done to avoid increasing the work required to create a client library in a new language, but actions turned out to be very important to packages like the navigation stack<sup>[1](#separatelib)</sup>.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*and MoveIt!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*"Navigation Stack"

In ROS 2 actions will be included in the client library implementations.
The work of writing a client library in a new language will be reduced by creating a common implmentation in C.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"implementation"


### Services used for Actions

In ROS 1 actions were implemented using a set of topics under a namespace taken from the action name.
ROS 1 Services were not used because they are inherently synchronous, and actions need to be asynchronous.
Actions also needed to send status/feedback and be cancelable.
In ROS 2 services are asynchronous in the common C implementation, so actions will use a combination of services and topics.

### Goal Identifiers

In ROS 1, Action clients are responsible for creating a goal ID when submitting a goal.
In ROS 2 the action server will be responsible for generating the goal ID and notifying the client.

The server is better equiped to generate a unique goal id than the client because there may be multiple clients who could independently generate the same goal id.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using a UUID may mitigate this, and still allow the client to 'know' the ID of a goal without ever talking to a server. This can be helpful when correlating 'actions' with other libraries/systems.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems reasonable. The original reason for having the server generate the ID is to avoid a race condition where the client may try to use the ID to cancel a goal before it is accepted. But in retrospect, by including the feature to "cancel all goals" or "cancel all goals before timestamp" we can still have a scenario where the cancel request arrives before a goal request. I guess this scenario can be resolved by processing requests as they arrive at the server; if a cancel request arrives first, then any subsequent goal requests are not retroactively canceled. Clients will still be informed that the goal is accepted via the goal response.

In the event that a client tries to use the explicit ID to cancel a goal before it is accepted, the server can reject the request if there are no goals with that ID in a valid state (PENDING or EXECUTING).

Therefore, I see no issue with allowing clients to generate a UUID.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You used the name "PENDING/EXECUTING" here -- I would suggest we actually use "ACCEPTED" and "EXECUTING" as the two state names -- it really tells you what stage the goal is in (accepted seems to have a better semantic meaning than pending, pending could mean that handle_goal() has yet to be called or something else. accepted really does state the the action server has acknowledged the goal, but not starting executing it).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But in retrospect, by including the feature to "cancel all goals" or "cancel all goals before timestamp" we can still have a scenario where the cancel request arrives before a goal request. I guess this scenario can be resolved by processing requests as they arrive at the server; if a cancel request arrives first, then any subsequent goal requests are not retroactively canceled

I wouldn't expect a goal to be cancellable until it has been accepted. Even if the goal is cancelled between the goal acceptance being transmitted from server to client then the client would still receive a response to its goal request indicating the goal was accepted, followed by a response to its result request indicating the goal was cancelled.

I guess the real problem in ROS 1 isn't the goal id generation, but that actionlib doesn't notify the client when a cancel request fails. It seems like the race condition is actually solved by cancel becoming a service.

using a UUID may mitigate this, and still allow the client to 'know' the ID of a goal without ever talking to a server. This can be helpful when correlating 'actions' with other libraries/systems.

A UUID generated by a client would work.

Another reason is to avoid a race condition between goal creation and cancellation that exists in ROS 1.
In ROS 1 if a client submits a goal and immediatly tries to cancel it then the cancelation may or may not happen.
If the cancelation is processed before the goal submission then `actionlib` will ignore the cancellation request without notifying the user's code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the term actionlib appears to be deprecated as you only use it twice in this document. please make this explicit, and be consistent with that you call this ROS2 feature

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this particular paragraph is describing the race condition in ROS1 -- so actionlib is the correct name -- but the wording should be updated to be more clear. Either break the last 3 sentences of this paragraph into their own paragraph (so they are logically collected), or add ROS1 somewhere in that last sentence so it is clear that it is describing the ROS1 error that is known, and which this change fixes.


### Namespacing of Generated Messages and Services

Multiple message and service definitions are generated from a single action definition.
In ROS 1, the generated messages were prefixed with the name of the action to avoid conflicts with other messages and services.
In ROS 2, the generated service and message definitions will exist in a different namespace to be impossible to conflict with non-action message and service definitions.
For example, in Python the code from the generated definitions should be in the module `action` instead of `srv` and `msg`.
In C++, the generated code should be in the namespace and folder `action` instead of `srv` and `msg`.

### Visibility of Action Services and Topics

In ROS 1 `rostopic list` would show all action topics in its output.
In ROS 2 `ros2 topic list` and `ros2 service list` will not show topics and services used by actions by default.
sloretz marked this conversation as resolved.
Show resolved Hide resolved
The can still be shown by passing an option to the commands to show hidden services and topics.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"They"


## Action Interface Definition

Actions are specified using a form of the ROS Message IDL.
The specification contains three sections, each of which is a message specification:

1. Goal

This describes what the action should achieve and how it should do it.
It is sent to the action server when it is requested to execute an action.

1. Result

This describes the outcome of an action.
It is sent from the server to the client when the action execution ends, whether successfully or not.

1. Feedback

This describes the progress towards completing an action.
It is sent to the client of the action from the action server between commencing action execution and prior to the action completing.
This data is used by the client to understand the progress of executing the action.

Any of these sections may be empty.
Between each of the three sections is a line containing three hyphens, `---`.
Action specifications are stored in a file ending in `.action`.
There is one action specification per `.action` file.

### Example

```
# Define a goal of washing all dishes
uint32 dishwasher_id # Specify which dishwasher we want to use
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't like this example if its going to be the example, because the solo dishwasher_id may be confused with the action ID. how about add another goal input e.g. bool heavy_duty # spend extra time cleaning

---
# Define the result that will be published after the action execution ends.
uint32 total_dishes_cleaned
---
# Define a feedback message that will be published during action execution.
float32 percent_complete
uint32 number_dishes_cleaned
```

## Introspection tools

Actions, like topics and services, are introspectable from the command line.
In ROS 1, actions are visible in the output of the `rostopic` tool.

In ROS 2, actions will not be visible by default as a set of topics nor a set of services.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove duplicate documentation here from Visibility of Action Services and Topics

Instead they will be visible using a separate `ros2 action` command line tool.

The command line tool will be able to:

* list action servers and action clients
* display active goals on an action server
* display the arguments for an action's goal
* display the type of an action's feedback and result
* find actions by action type
* call an action, display feedback as it is received, display the result when received, and cancel the action (when the tool is terminated prematurely).

Each action will be listed and treated as a single unit by this tool.

## Goal States

The action server maintains a state machine for each goal it accepts from a client.
Rejected goals are not part of the state machine.

![Action Server State Machine](../img/actions/action_server_state_machine.png)

There are two active states:

- **EXECUTING** - The goal has been accepted and is currently being executed by the action server.
- **CANCELING** - The client has requested that the goal be canceled and the action server has accepted the cancel request.
This state is useful for any "clean up" that the action server may have to do.
sloretz marked this conversation as resolved.
Show resolved Hide resolved

And three terminal states:

- **SUCCEEDED** - The goal was achieved successfully by the action server.
- **ABORTED** - The goal was terminated by the action server without an external request.
- **CANCELED** - The goal was canceled after an external request from an action client.

State transitions triggered by the action server:

- **set_succeeded** - Notify that the goal completed successfully.
jacobperron marked this conversation as resolved.
Show resolved Hide resolved
- **set_aborted** - Notify that an error was encountered during processing of the goal and it had to be aborted.
- **set_canceled** - Notify that canceling the goal completed successfully.

State transitions triggered by the action client:

- **send_goal** - A goal is sent to the action server.
The state machine is only started if the action server *accepts* the goal.
- **cancel_goal** - Request that the action server stop processing the goal.
A transition only occurs if the action server *accepts* the request to cancel the goal.
The goal may transition to CANCELING or CANCELED depending on the action server implementation.

## API

Proposed examples can be in the respository [examples (branch: actions_proposal)](https://github.com/ros2/examples/tree/actions_proposal).

C++:

- [examples/rclcpp/minimal_action_server](https://github.com/ros2/examples/tree/actions_proposal/rclcpp/minimal_action_server)
- [examples/rclcpp/minimal_action_client](https://github.com/ros2/examples/tree/actions_proposal/rclcpp/minimal_action_client)

Python:

- [examples/rclpy/actions](https://github.com/ros2/examples/tree/actions_proposal/rclpy/actions)

## Middleware implementation

Under the hood, an action is made up of three services and two topics, each descibed in detail here.

![Action Client/Server Interaction Overview](../img/actions/interaction_overview.png)

### Goal Submission Service

* **Direction**: Client calls Server
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sometimes you capitalize "Server" and sometimes you do not, be consistent

* **Request**: Description of goal
* **Response**: Whether goal was accepted or rejected, a unique identifier for the goal, and the time when the goal was accepted.

The purpose of this service is to submit a goal to the action server.
It is the first service called to begin an action, and is expected to return quickly.
A user-define description of the goal is sent as the request.
The response indicates whether or not the goal was accepted, and if so the identifier the server will use to describe the goal.

The QoS settings of this service should be set the so the client is guaranteed to receive a response or an action could be executed without a client being aware of it.

### Cancel Request Service
clalancette marked this conversation as resolved.
Show resolved Hide resolved

* **Direction**: Client calls Server
* **Request**: Goal identifier, time stamp
* **Response**: Goals that will be attempted to be canceled

The purpose of this service is to request to cancel one or more goals on the action server.
A cancellation request may cancel multiple goals.
The result indicates which goals will be attempted to be canceled.
Whether or not a goal is actually canceled is indicated by the status topic and the result service.
clalancette marked this conversation as resolved.
Show resolved Hide resolved

The cancel request policy is the same as in ROS 1.

* If the goal ID is empty and time is zero, cancel all goals
* If the goal ID is empty and time is not zero, cancel all goals accepted at or before the time stamp
* If the goal ID is not empty and time is not zero, cancel the goal with the given id regardless of the time it was accepted
* If the goal ID is not empty and time is zero, cancel the goal with the given id and all goals accepted at or before the time stamp

### Get Result Service
jacobperron marked this conversation as resolved.
Show resolved Hide resolved

* **Direction**: Client calls Server
* **Request**: Goal ID
* **Response**: Status of goal and user defined result

The purpose of this service is to get the final result of a service.
After a goal has been accepted the client should call this service to receive the result.
sloretz marked this conversation as resolved.
Show resolved Hide resolved
The result will indicate the final status of the goal and any user defined data.

Once the server sends the result to the client it should free up any resources used by the action.
If the client never asks for the result then the server should discard the result after a timeout period.

### Goal Status Topic

* **Direction**: Server publishes
* **Content**: List of in-progress goals with: Goal ID, time accepted, and an enum indicating the status

This topic is published by the server to broadcast the status of goals it has accepted.
Copy link

@paulbovbel paulbovbel Oct 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same problem as feedback (https://github.com/ros2/design/pull/193/files#r225264321) with clients receiving data they don't care about. Additionally, there are issues where a 'lost on the wire' status message could cause a failure to transition properly client side.

I think it's really important to consider how this respin of actions is going to work on unreliable networks, as that's one of the major applications (and goals?) of ROS2/DDS.

Reading over this and the 'get_result' section above, would it make sense to have the action server 'push' results and statuses to clients via a service? It would be up to the client to specify a callback where to process the results for any submitted goals.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same problem as feedback (https://github.com/ros2/design/pull/193/files#r225264321) with clients receiving data they don't care about.

I don't think a client will subscribe to this topic. It is meant for introspection only.

Additionally, there are issues where a 'lost on the wire' status message could cause a failure to transition properly client side.

I think it's really important to consider how this respin of actions is going to work on unreliable networks, as that's one of the major applications (and goals?) of ROS2/DDS.

Agreed. The QoS settings definitely need to be exposed to the user.

Reading over this and the 'get_result' section above, would it make sense to have the action server 'push' results and statuses to clients via a service? It would be up to the client to specify a callback where to process the results for any submitted goals.

Since ROS 2 services are asynchronous (in rcl and rclpy, exposing this in rclcpp is tracked in ros2/rclcpp#491) I think the result is the same. Calling get_result is like asking the server to push the result to the action client in the future. It just happens the action result is communicated as the response to a service call.

Copy link

@paulbovbel paulbovbel Oct 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think a client will subscribe to this topic. It is meant for introspection only.

Thanks for clarifying that, I assumed too much carried over from ROS1 actionlib. This picture should be updated (https://github.com/ros2/design/blob/5de40c7802fb39d71ea3489cc6a6ac65e17c61aa/img/actions/interaction_overview.png).

I think the result is the same

If the result is the same, then unless I'm missing something, the point of having the client call a service to retrieve the result, is to avoid having the result proliferated to every client via topic, otherwise the 'request' portion of get_result seems redundant.

If that assumption is correct, then there exists a similar problem for the feedback comms (proliferation to all connected clients). It seems like it would make sense to use the same approach for both - i.e. the client repeatedly calling a get_feedback service.

Based on https://github.com/ros2/design/pull/193/files#r225325429, it may then make sense to migrate to a 'keyed' topic based on goal id for both feedback and result once the mechanism is available.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the result is the same, then unless I'm missing something, the point of having the client call a service to retrieve the result, is to avoid having the result proliferated to every client via topic, otherwise the 'request' portion of get_result seems redundant.

That case wasn't considered. The assumption is that there are usually only a handful of clients (in most cases just one) per server. Are you currently using many action clients per server in ROS 1? If so, how well does it perform?

Services make some parts of the client implementation simpler. The client doesn't need to track the server's state machine. wait_for_action_server could reuse wait_for_service. It does have a drawback that for clients who never fetch the result, the server will have to decide how long to hold onto it before discarding it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Starting to get our 'results' mixed up :)

I've seen low-to-mid double digits clients per server. To some degree that's probably because of how inflexible 'services' were in ROS1, but regardless...

I don't want to advise for over-optimization, and I appreciate that with a central rcl implementation of action comms, you have the option to restructure 'later', but it may be worthwhile to make certain scaling-friendly decisions up front. Transmitting N results/feedbacks to M clients over a potentially limited comms channel feels like one of those decisions. If get_result is an acceptable strategy, then maybe get_feedback is as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think a client will subscribe to this topic. It is meant for introspection only.

Even though the internal workings of an action client doesn't need to know the status of a goal, I can see it being convenient for application developers to have access to the status via the action client API. This means the client would subscribe to the status topic.

Otherwise, assuming the topic is in some hidden namespace, it seems awkward for a developer to create a subscriber to _action/fibonacci/status to get the status.

If bandwidth/processing is a concern, we could make the status subscriber optional at the C API level. The same could be done for the feedback topic. But I'm leaning towards waiting for the DDS "keyed data" feature that was mentioned in #193 (comment) to be exposed and make use of that to address resource usage concerns, which seems like a more elegant solution IMO.

The purpose of the topic is for introspection; it is not used by the action client.
Messages are published when transitions from one status to another occur.

The default QoS settings for a DDS middleware should be TRANSIENT LOCAL with a history size of 1.
This allows new subscribers to always get the latest state.

The possible statuses are:

* *Accepted*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that "accepted" / "executing" are different between goal states above, and here.

* The goal has been accepted by the action server and may now be executing
* *Cancelling*
* The action server will try to cancel the indicated goal
* *Cancelled*
* The action server successfully canceled the goal
* *Succeeded*
* The action server successfully reached the goal
* *Aborted*
* The action server failed reached the goal

### Feedback Topic
jacobperron marked this conversation as resolved.
Show resolved Hide resolved

* **Direction**: Server publishes
* **Content**: Goal id, user defined feedback message

This topic is published by the server to send application specific progress about the goal.
It is up to the author of the action server to decide how often to publish the feedback.
jacobperron marked this conversation as resolved.
Show resolved Hide resolved

### Client/Server Interaction Examples

Here are a couple of sequence diagrams depicting typical interactions between an action client and action server.

#### Example 1

In this example, the action client request a goal and gets a response from the server accepting the goal (synchronous).
jacobperron marked this conversation as resolved.
Show resolved Hide resolved
Upon accepting the goal, the action server starts a user defined execution method for completing the goal.
Following the goal request, the client makes an asynchronous request for the result.
The user defined method publishes feedback to the action client as it executes the goal.
Ultimately, the user defined method populates a result message that is used as part of the result response.

![Goal Lifecycle Example 0](../img/actions/interaction_example_0.png)

#### Example 2

This example is almost identical to the first, but this time the action client requests for the goal to be canceled mid-execution.
clalancette marked this conversation as resolved.
Show resolved Hide resolved
jacobperron marked this conversation as resolved.
Show resolved Hide resolved
Note that the user defined method is allowed to perform any shutdown operations after the cancel request before returning with the cancellation result.

![Goal Lifecycle Example 1](../img/actions/interaction_example_1.png)

#### Example 3

Here is a more complex example involving multiple goals.

TODO
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Member

@jacobperron jacobperron Oct 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add one or two more example sequence diagrams. I wasn't sure if it would be too cluttered to be useful; feedback is welcome on any scenarios that might benefit from a sequence diagram for clarity.


## Bridging between ROS 1 and ROS 2

TODO
jacobperron marked this conversation as resolved.
Show resolved Hide resolved

## Alternatives

These alternative approaches to actions in ROS 2 were considered.

### Actions in rmw

An alternative to using services and topics is to implement actions in the rmw layer.
This would enable using middleware specific features better suited actions.
jacobperron marked this conversation as resolved.
Show resolved Hide resolved
The default middleware in ROS 2 uses DDS, and there don't appear to be any DDS features better for actions than what are used for services and topics.
Additionally implementing actions in the rmw implementations increases the complexity of writing an rmw implementation.
For these reasons actions will be implemented at a higher level.

## References

1. <a name="separatelib" href="https://discourse.ros.org/t/actions-in-ros-2/6254/5">https://discourse.ros.org/t/actions-in-ros-2/6254/5</a>
Binary file added img/actions/action_server_state_machine.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/actions/interaction_example_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/actions/interaction_example_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/actions/interaction_overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.