-
Notifications
You must be signed in to change notification settings - Fork 194
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
Design actions API and implementation #183
Conversation
A grab-bag of opinions based on my experience with actionlib(1):
There's quite a few interesting cases that come up when the link is not reliable:
It may be worthwhile to consider how actionlib(2) should work in these situations. Even if a base
|
I agree with point 1 in your list @paulbovbel That was basically what I was thinking in my "option 2" in the #143 thread. I don't know of any benefit of plumbing down to the rmw layer, but would also want @wjwwood or @tfoote to comment if they know of a better way to implement it. |
The |
I agree, |
I've reviewed this design proposal and, aside from some missing sections, it seems okay to me. A few thoughts: Can you add a section specifically calling out how actionlib2 will be different than 1? Aside from using ROS2 under the hood of course? It appears to be the same from my initial read, which I think is a good thing. I see it will be treated as a "first class citizen" but how does that actually pan out? I've never seen any issues using actionlib1 in ROS as a second class citizen except that its missing some of the introspection tools that messages and services have. I'd like to mention one thing I didn't like about actionlib1 is that it had two different server interfaces - the SimpleActionServer and the not simple one. This always felt hacky and complicated and I'd prefer just one approach. |
+1 This re-opened some memories. I feel like the SimpleActionClient/Server came baked in with some surprises, due to the implicit background thread and goal preemption handling. IMO what would be a much 'simpler' experience for a ROS beginner is a small tutorial on 'How to write an action server callback to only have one goal active at a time', along the lines of:
I always interpreted this as a commitment to having actions in the |
So if I understand correctly the implementation of an Action service would be to create action structs at the rcl layer that contain at least one service for the async call / response, and at least one feedback topic. How would the cancellation work? Is that via the same service interface (a null for the goal_handle in the callback example given above) or is there a third connection needed to cancel a pending request? |
Either is possible, I had always imagined having a separate service for canceling, perhaps just one per node, no matter how many action servers there were or perhaps one for each action server. But you could also "inject" an "action" enum into the request message, so it looked something like (roughly
Ideally we would never do this, since each Service type would ideally only deal with a single task, because that makes the types easier to understand and easier to reuse. It also reduces the inserted "magic" on top of what the user expressed in their request/feedback/response definition. However, we may be compelled to do this for performance reasons (yet to be seen how much overhead each Service causes). |
So an action server would have 2 services, one for executing the action, one for cancelling it, and one feedback topic that it publishes. |
@mkhansen-intel Yes, that's how I imagined it. But as I said, we might have to be pragmatic if we run into scaling issues or something. In the past we had thought perhaps that all Services would be preemptible, but that was before we decided to delegate to DDS based RPC calls for the first implementation. In which case actions would have just been one (preemptible) service and a topic. |
So what should the behavior be if a second command is issued while one is in progress, should it pre-empt the first, same as cancelling? Or should it queue the second command? Or should that be a configurable option for each action? |
Also, I'm not very familiar with the message generation / parsing code. I think the changes needed for parsing would be in https://github.com/ros2/rosidl/blob/master/rosidl_parser/rosidl_parser/__init__.py
And for generation, changes would be here: https://github.com/ros2/rosidl/blob/master/rosidl_generator_cpp/rosidl_generator_cpp/__init__.py
Am I missing more that would need to happen to generate the messages? What about tools changes? |
As an alternative to what I said above, I guess we wouldn't have to define an action message type at all, it could be kept separate as 2 services and a message. It wouldn't have the syntactic niceness that the current ActionLib has of defining it all in one .action file though. Thoughts? |
This sounds about right 👍 One thing to figure out is how we expect users to interact with the generated datastructures (in what namespace the generated structure should live etc).
The other generators should be updated accordingly ( |
I would say it should be possible to have multiple actions in flight simultaneously and have an option to only have one at a time. You should also consider if that's requests from all requesters or from individual requesters. In ROS 1, it's possible to have more than one at a time (you basically just provide callbacks for when a goal is received and when a goal is canceled): https://docs.ros.org/api/actionlib/html/classactionlib_1_1ActionServer.html But the simple action server class (which some people complained about being a separate thing) provides the "single goal at a time" behavior which is desirable in many cases, and maybe should even be the default, but I'm not sure: https://wiki.ros.org/actionlib#SimpleActionServer_Goal_Policies |
Thanks for all the feedback. I'm going to update the article over the next couple of days. @mkhansen-intel Do you have a repository where prototyping work is being done? |
@gbiggs - no I don't have a repo for this. I am mainly trying to figure out how to spur it along to keep it from blocking the ros-planning/navigation2 project. I'd be willing to do some of the work but not sure I can take it all on myself, especially since I haven't made changes in most of these layers before, I'm used to using the rclcpp layer interface. My thinking right now is that to provide what the navigation2 project needs in the short term, I would probably implement the rclcpp node interface, with ActionServer and ActionClient classes that wrap the Service and Client classes at that level, and leave the other work for OSRF to implement when they have time. I know that's not ideal in the long term. Alternately, if someone else was willing to do the rcl layer work, I would be willing to do the rclcpp layer to use that instead, and we could work together on a fork until it was ready for submitting the PRs for both. I'm just not confident I could do everything in a timely fashion, as I'm not an expert in these layers. |
So, how compatible with the existing ROS ActionLib interface should this be? Does it need to be an exact match? |
Do you mean at the API level or on the wire? For the API level, similar is good but I wouldn't hesitate to change the API if it makes sense (sometimes you have to do so, especially where assumptions about the node singleton in ROS 1 are involved). We should also give some thought to how this could be mapped over the bridge. We don't need to implement that now, but if actions are conceptually different in ROS 2 somehow, then it might become impossible to bridge them across the |
@wjwwood - Here is a branch where I've added a node->create_action_server() and node->create_action_client(). https://github.com/mkhansen-intel/rclcpp/tree/actions And here is a branch for examples for both. https://github.com/mkhansen-intel/examples/tree/action_examples These are both purely in the rclcpp layer and not plumbed through to the rcl layer. Also, I've not implemented the tools changes to generate the actions message types from an actions file. So for right now, the API requires a Service (ie. AddTwoInts) and a Feedback message type (ie. std_msgs/String). See the examples. Later this could be combined into one template argument. I think this is enough to start with for our team doing Navigation2, with the expectation that when the tools changes could be implemented and *.action files supported, we could easily change the template interface to one . In order to send a request to the server, it's using a client->send_async_request() and to cancel it is client->cancel_request(). Right now cancel_request() is not returning any status, if we want it to have a status, we would need to talk about how to do that. Also, I haven't implemented any state machine for the client. This is all purely callbacks, and the expectation right now is that the node itself is implementing some state machine if it is needed. Do we want a state machine? If so wouldn't that be implemented in the rcl layer? Please take a look and let me know your thoughts and whether this is a useful starting point. If you want I can submit a PR to allow for comments there too. |
@wjwwood, @mikaelarguedas @gbiggs - please take a look at my post above and provide some feedback. |
All, I want to continue work on this but need some guidance / direction. I know that ActionLib implemented state machines for the Client and Server: http://wiki.ros.org/actionlib/DetailedDescription Is the design goal to make Actions in ROS2 fully equivalent to the ActionLib Actions? If so, these state machines are needed, right? Also, what about the APIs? I see this: http://docs.ros.org/lunar/api/actionlib/html/classactionlib_1_1SimpleActionClient.html Are we aiming for API compatability with equivalent functions for all of these in ROS2? |
I might not be the best person to answer these questions, but here are my thoughts:
I would grealy prefer this so that current usages of actionlib (e.g. everywhere in MoveIt!) are easy to port to ROS2
Yes, even being able to re-use a lot of this documentation would be great
I don't think API compatibility is necessary... it should instead look and feel like the new ROS2 API for services and messages. Hopefully we can find-replace a lot of the old API to port to the new API |
Those look reasonable on their own. I haven't tried comparing them to ROS 1's examples for actions to see how they differ.
I guess that's ok, but you could also go ahead and create a structure which contains the composition of the two message/service types as an "action". Then in the future you'd just pass a different struct (provided by the generated code). |
Hmm, I'm concerned about this because you're not going to be able to use the existing action definitions and instead will have to create new messages and services based on them in the meantime. I suppose that's fine, but it would obviously be better to get action file generation going.
It also appears to be the same type as the request/response service... I would have thought it would be a standard Type like https://github.com/ros2/common_interfaces/blob/master/std_srvs/srv/Trigger.srv.
Equivalent in usage and functionality, yes, but not necessarily in implementation details.
I don't think we will need the state machine as-is from actionlib in ROS 1 because we're using services in ROS 2 whereas in ROS 1 actionlib used topics for everything (IIRC). But I think we might need a state machine of some sort. I can't answer this without digging into the details (http://wiki.ros.org/actionlib/DetailedDescription) and figuring out what applies to our approach in ROS 2 and what doesn't anymore. Someone will need to do that and ideally them summarize their conclusions in the design document. Perhaps there's a reason buried in the details description of actionlib which gives a reason that they went with all topics and a state machine rather than using two services (request/reply and cancel). Honestly using topics for everything just like it was done in ROS 1 is still on the table for me, but naively it appears the services would make it simpler.
As @davetcoleman mentioned, we should have equivalent API's so that porting is straight forward, but updating them to match the style of ROS 2 or to take advantage of a new feature is fine. We already discussed above that there's a "simple" and full API for actions in ROS 1, but I honestly don't know if we need the same in ROS 2. My initial thought is to implement the normal API and at that point we can consider whether or not we need to have something equivalent to the simple API, because we should be able to add on the simpler API at any point since my impression is that it's only syntactic sugar. |
Thanks for the input, I can easily make the change to the cancel to use the Trigger service type, I wasn't aware of that one. I think we need more clarity of the design, who is leading this from OSRF? |
No one is spending time on actions right now. Originally we planned to have 4-ish people on Actions in October, but I don't know if that's still the plan or not. |
Maybe we can discuss in person at ROSCon? |
I'm sorry for leaving this for so long. My time is not (yet) my own. I'd like to discuss at ROSCon and come up with a plan of attack so we can deal with actions on all fronts in a coordinated way: the design document, the rclc layer, and the client libraries built on top of that. |
@gbiggs - It would be great to meet at ROSCon and discuss, let me know when and where |
Let's set up a birds of a feather meeting during the time allocated for those. |
Unfortunately there are no BOF sessions this year. All I saw was this post on discourse: https://discourse.ros.org/t/roscon-2018-informal-meetings-of-special-interest-groups/6151 We could potentially meet during the lunch hour somewhere. |
Lunch on the first day seems open. |
@gbiggs What would you like to see happen to this PR and #193? Here are a couple options for your consideration, there may be more.
|
I'm happy for this to be closed and #193 called a continuation of it. |
Understood, I'll close it then. Continued in #193 |
This is a continuation of #143, but without the messed up git history.
I have cleaned up the formatting and revised some of the information, but there is still a lot of work to be done on design. My hope is that we can fill it out based on prototypes and the needs of the navstack2 work.