-
Notifications
You must be signed in to change notification settings - Fork 315
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Copy rclpy action examples from #216 * Bump version of examples_rclpy_action to match other packages * Consolidate composable action client example * Add action client example that is not composable * Wait for action server * Restructure into separate packages for action client and action server examples This package structure is consistent with examples for services and topics. * Update API in action server examples * Rename action server examples Now the 'simplest' example is 'server.py'. * Add action server example that is not composable * Update setup.py * Fix syntax * Update action client examples to use goal handle API for the result Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Improve action client output and result handling Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Update action server examples Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Move action examples into Python packages This avoid top-level module names from clashing when installed. Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Add action client cancel example Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Address review comments * Update author * Update copyright year * Shutdown client example after result received Signed-off-by: Jacob Perron <jacob@openrobotics.org> * GoalResponse.ACCEPT_AND_EXECUTE -> GoalResponse.ACCEPT Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Fix client_cancel example Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Remove race from server_single_goal example Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Add action server example that defers the execution of an accepted goal Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Reduce the timer period for the client cancel example This makes it easy to experiment with the scenario where a deferred goal is canceled prior to execution. Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Support canceling goals with non-composable action server example Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Add action server example that queues goals Signed-off-by: Jacob Perron <jacob@openrobotics.org> * Address review - Fix comment - Add author tag to package.xml Signed-off-by: Jacob Perron <jacob@openrobotics.org>
- Loading branch information
1 parent
2dbcf9f
commit cfc9bc6
Showing
18 changed files
with
944 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
82 changes: 82 additions & 0 deletions
82
rclpy/actions/minimal_action_client/examples_rclpy_minimal_action_client/client.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Copyright 2018 Open Source Robotics Foundation, Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from action_msgs.msg import GoalStatus | ||
from example_interfaces.action import Fibonacci | ||
|
||
import rclpy | ||
from rclpy.action import ActionClient | ||
from rclpy.node import Node | ||
|
||
|
||
class MinimalActionClient(Node): | ||
|
||
def __init__(self): | ||
super().__init__('minimal_action_client') | ||
self._action_client = ActionClient(self, Fibonacci, 'fibonacci') | ||
|
||
def goal_response_callback(self, future): | ||
goal_handle = future.result() | ||
if not goal_handle.accepted: | ||
self.get_logger().info('Goal rejected :(') | ||
return | ||
|
||
self.get_logger().info('Goal accepted :)') | ||
|
||
self._get_result_future = goal_handle.get_result_async() | ||
self._get_result_future.add_done_callback(self.get_result_callback) | ||
|
||
def feedback_callback(self, feedback): | ||
self.get_logger().info('Received feedback: {0}'.format(feedback.sequence)) | ||
|
||
def get_result_callback(self, future): | ||
status = future.result().action_status | ||
if status == GoalStatus.STATUS_SUCCEEDED: | ||
self.get_logger().info('Goal succeeded! Result: {0}'.format(future.result().sequence)) | ||
else: | ||
self.get_logger().info('Goal failed with status: {0}'.format(status)) | ||
|
||
# Shutdown after receiving a result | ||
rclpy.shutdown() | ||
|
||
def send_goal(self): | ||
self.get_logger().info('Waiting for action server...') | ||
self._action_client.wait_for_server() | ||
|
||
goal_msg = Fibonacci.Goal() | ||
goal_msg.order = 10 | ||
|
||
self.get_logger().info('Sending goal request...') | ||
|
||
self._send_goal_future = self._action_client.send_goal_async( | ||
goal_msg, | ||
feedback_callback=self.feedback_callback) | ||
|
||
self._send_goal_future.add_done_callback(self.goal_response_callback) | ||
|
||
|
||
def main(args=None): | ||
rclpy.init(args=args) | ||
|
||
action_client = MinimalActionClient() | ||
|
||
action_client.send_goal() | ||
|
||
rclpy.spin(action_client) | ||
|
||
action_client.destroy_node() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
94 changes: 94 additions & 0 deletions
94
rclpy/actions/minimal_action_client/examples_rclpy_minimal_action_client/client_cancel.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# Copyright 2019 Open Source Robotics Foundation, Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from action_msgs.msg import GoalStatus | ||
from example_interfaces.action import Fibonacci | ||
|
||
import rclpy | ||
from rclpy.action import ActionClient | ||
from rclpy.callback_groups import ReentrantCallbackGroup | ||
from rclpy.node import Node | ||
from rclpy.timer import WallTimer | ||
|
||
|
||
class MinimalActionClient(Node): | ||
|
||
def __init__(self): | ||
super().__init__('minimal_action_client') | ||
self._action_client = ActionClient(self, Fibonacci, 'fibonacci') | ||
|
||
def cancel_done(self, future): | ||
cancel_response = future.result() | ||
if len(cancel_response.goals_canceling) > 0: | ||
self.get_logger().info('Goal successfully canceled') | ||
else: | ||
self.get_logger().info('Goal failed to cancel') | ||
|
||
rclpy.shutdown() | ||
|
||
def goal_response_callback(self, future): | ||
goal_handle = future.result() | ||
if not goal_handle.accepted: | ||
self.get_logger().info('Goal rejected :(') | ||
return | ||
|
||
self._goal_handle = goal_handle | ||
|
||
self.get_logger().info('Goal accepted :)') | ||
|
||
# Start a 2 second timer | ||
self._timer = self.create_timer(2.0, self.timer_callback) | ||
|
||
def feedback_callback(self, feedback): | ||
self.get_logger().info('Received feedback: {0}'.format(feedback.sequence)) | ||
|
||
def timer_callback(self): | ||
self.get_logger().info('Canceling goal') | ||
# Cancel the goal | ||
future = self._goal_handle.cancel_goal_async() | ||
future.add_done_callback(self.cancel_done) | ||
|
||
# Cancel the timer | ||
self._timer.cancel() | ||
|
||
def send_goal(self): | ||
self.get_logger().info('Waiting for action server...') | ||
self._action_client.wait_for_server() | ||
|
||
goal_msg = Fibonacci.Goal() | ||
goal_msg.order = 10 | ||
|
||
self.get_logger().info('Sending goal request...') | ||
|
||
self._send_goal_future = self._action_client.send_goal_async( | ||
goal_msg, | ||
feedback_callback=self.feedback_callback) | ||
|
||
self._send_goal_future.add_done_callback(self.goal_response_callback) | ||
|
||
|
||
def main(args=None): | ||
rclpy.init(args=args) | ||
|
||
action_client = MinimalActionClient() | ||
|
||
action_client.send_goal() | ||
|
||
rclpy.spin(action_client) | ||
|
||
action_client.destroy_node() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
77 changes: 77 additions & 0 deletions
77
...tions/minimal_action_client/examples_rclpy_minimal_action_client/client_not_composable.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# Copyright 2019 Open Source Robotics Foundation, Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from action_msgs.msg import GoalStatus | ||
|
||
from example_interfaces.action import Fibonacci | ||
|
||
import rclpy | ||
from rclpy.action import ActionClient | ||
from rclpy.node import Node | ||
|
||
|
||
def feedback_cb(logger, feedback): | ||
logger.info('Received feedback: {0}'.format(feedback.sequence)) | ||
|
||
|
||
def main(args=None): | ||
rclpy.init(args=args) | ||
|
||
node = rclpy.create_node('minimal_action_client') | ||
|
||
action_client = ActionClient(node, Fibonacci, 'fibonacci') | ||
|
||
node.get_logger().info('Waiting for action server...') | ||
|
||
action_client.wait_for_server() | ||
|
||
goal_msg = Fibonacci.Goal() | ||
goal_msg.order = 10 | ||
|
||
node.get_logger().info('Sending goal request...') | ||
|
||
send_goal_future = action_client.send_goal_async( | ||
goal_msg, feedback_callback=lambda feedback: feedback_cb(node.get_logger(), feedback)) | ||
|
||
rclpy.spin_until_future_complete(node, send_goal_future) | ||
|
||
goal_handle = send_goal_future.result() | ||
|
||
if not goal_handle.accepted: | ||
node.get_logger().info('Goal rejected :(') | ||
action_client.destroy() | ||
node.destroy_node() | ||
rclpy.shutdown() | ||
return | ||
|
||
node.get_logger().info('Goal accepted :)') | ||
|
||
get_result_future = goal_handle.get_result_async() | ||
|
||
rclpy.spin_until_future_complete(node, get_result_future) | ||
|
||
status = get_result_future.result().action_status | ||
if status == GoalStatus.STATUS_SUCCEEDED: | ||
node.get_logger().info( | ||
'Goal succeeded! Result: {0}'.format(get_result_future.result().sequence)) | ||
else: | ||
node.get_logger().info('Goal failed with status code: {0}'.format(status)) | ||
|
||
action_client.destroy() | ||
node.destroy_node() | ||
rclpy.shutdown() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?xml version="1.0"?> | ||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> | ||
<package format="2"> | ||
<name>examples_rclpy_minimal_action_client</name> | ||
<version>0.6.1</version> | ||
<description>Examples of minimal action clients using rclpy.</description> | ||
|
||
<maintainer email="sloretz@openrobotics.org">Shane Loretz</maintainer> | ||
<license>Apache License 2.0</license> | ||
|
||
<author email="jacob@openrobotics.org">Jacob Perron</author> | ||
|
||
<exec_depend>example_interfaces</exec_depend> | ||
<exec_depend>rclpy</exec_depend> | ||
|
||
<!-- These test dependencies are optional | ||
Their purpose is to make sure that the code passes the linters --> | ||
<test_depend>ament_copyright</test_depend> | ||
<test_depend>ament_flake8</test_depend> | ||
<test_depend>ament_pep257</test_depend> | ||
<test_depend>python3-pytest</test_depend> | ||
|
||
<export> | ||
<build_type>ament_python</build_type> | ||
</export> | ||
</package> |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[develop] | ||
script-dir=$base/lib/examples_rclpy_minimal_action_client | ||
[install] | ||
install-scripts=$base/lib/examples_rclpy_minimal_action_client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from setuptools import setup | ||
|
||
package_name = 'examples_rclpy_minimal_action_client' | ||
|
||
setup( | ||
name=package_name, | ||
version='0.6.1', | ||
packages=[package_name], | ||
data_files=[ | ||
('share/ament_index/resource_index/packages', | ||
['resource/' + package_name]), | ||
('share/' + package_name, ['package.xml']), | ||
], | ||
install_requires=['setuptools'], | ||
zip_safe=True, | ||
author='Jacob Perron', | ||
author_email='jacob@openrobotics.org', | ||
maintainer='Shane Loretz', | ||
maintainer_email='sloretz@openrobotics.org', | ||
keywords=['ROS'], | ||
classifiers=[ | ||
'Intended Audience :: Developers', | ||
'License :: OSI Approved :: Apache Software License', | ||
'Programming Language :: Python', | ||
'Topic :: Software Development', | ||
], | ||
description='Examples of action clients using rclpy.', | ||
license='Apache License, Version 2.0', | ||
tests_require=['pytest'], | ||
entry_points={ | ||
'console_scripts': [ | ||
'client = ' + package_name + '.client:main', | ||
'client_cancel = ' + package_name + '.client_cancel:main', | ||
'client_not_composable = ' + package_name + '.client_not_composable:main', | ||
], | ||
}, | ||
) |
Empty file.
Oops, something went wrong.