-
Notifications
You must be signed in to change notification settings - Fork 479
Implement generic client #2358
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
Merged
fujitatomoya
merged 10 commits into
ros2:rolling
from
Barry-Xu-2018:review/topic-generic-client-support
Mar 5, 2024
Merged
Implement generic client #2358
Changes from 9 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
beeadfc
Implement generic client
Barry-Xu-2018 a1fca1a
Fix the incorrect parameter declaration
Barry-Xu-2018 5906087
Deleted copy constructor and assignment for FutureAndRequestId
Barry-Xu-2018 8ef18fe
Update codes after rebase
Barry-Xu-2018 f3933cf
Address review comments
Barry-Xu-2018 8540fe6
Address review comments from iuhilnehc-ynos
Barry-Xu-2018 a73f5ed
Correct an error in a description
Barry-Xu-2018 da86048
Fix window build errors
Barry-Xu-2018 69145c4
Address review comments from William
Barry-Xu-2018 6f0cec6
Add doc strings to create_generic_client
Barry-Xu-2018 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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,78 @@ | ||
| // Copyright 2023 Sony Group Corporation. | ||
| // | ||
| // 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. | ||
|
|
||
| #ifndef RCLCPP__CREATE_GENERIC_CLIENT_HPP_ | ||
| #define RCLCPP__CREATE_GENERIC_CLIENT_HPP_ | ||
|
|
||
| #include <memory> | ||
| #include <string> | ||
|
|
||
| #include "rclcpp/generic_client.hpp" | ||
| #include "rclcpp/node_interfaces/get_node_base_interface.hpp" | ||
| #include "rclcpp/node_interfaces/get_node_graph_interface.hpp" | ||
| #include "rclcpp/node_interfaces/get_node_services_interface.hpp" | ||
| #include "rclcpp/node_interfaces/node_base_interface.hpp" | ||
| #include "rclcpp/node_interfaces/node_graph_interface.hpp" | ||
| #include "rclcpp/node_interfaces/node_services_interface.hpp" | ||
| #include "rclcpp/qos.hpp" | ||
|
|
||
| namespace rclcpp | ||
| { | ||
| /// Create a generic service client with a name of given type. | ||
| /** | ||
| * \param[in] node_base NodeBaseInterface implementation of the node on which | ||
| * to create the client. | ||
| * \param[in] node_graph NodeGraphInterface implementation of the node on which | ||
| * to create the client. | ||
| * \param[in] node_services NodeServicesInterface implementation of the node on | ||
| * which to create the client. | ||
| * \param[in] service_name The name on which the service is accessible. | ||
| * \param[in] service_type The name of service type, e.g. "test_msgs/srv/BasicTypes" | ||
| * \param[in] qos Quality of service profile for client. | ||
| * \param[in] group Callback group to handle the reply to service calls. | ||
| * \return Shared pointer to the created client. | ||
| */ | ||
wjwwood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| RCLCPP_PUBLIC | ||
| rclcpp::GenericClient::SharedPtr | ||
| create_generic_client( | ||
| std::shared_ptr<node_interfaces::NodeBaseInterface> node_base, | ||
| std::shared_ptr<node_interfaces::NodeGraphInterface> node_graph, | ||
| std::shared_ptr<node_interfaces::NodeServicesInterface> node_services, | ||
| const std::string & service_name, | ||
| const std::string & service_type, | ||
| const rclcpp::QoS & qos = rclcpp::ServicesQoS(), | ||
| rclcpp::CallbackGroup::SharedPtr group = nullptr); | ||
wjwwood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| template<typename NodeT> | ||
fujitatomoya marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| rclcpp::GenericClient::SharedPtr | ||
| create_generic_client( | ||
| NodeT node, | ||
| const std::string & service_name, | ||
| const std::string & service_type, | ||
| const rclcpp::QoS & qos = rclcpp::ServicesQoS(), | ||
| rclcpp::CallbackGroup::SharedPtr group = nullptr) | ||
| { | ||
| return create_generic_client( | ||
| rclcpp::node_interfaces::get_node_base_interface(node), | ||
| rclcpp::node_interfaces::get_node_graph_interface(node), | ||
| rclcpp::node_interfaces::get_node_services_interface(node), | ||
| service_name, | ||
| service_type, | ||
| qos, | ||
| group | ||
| ); | ||
| } | ||
| } // namespace rclcpp | ||
|
|
||
| #endif // RCLCPP__CREATE_GENERIC_CLIENT_HPP_ | ||
This file contains hidden or 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,207 @@ | ||
| // Copyright 2023 Sony Group Corporation. | ||
| // | ||
| // 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. | ||
|
|
||
| #ifndef RCLCPP__GENERIC_CLIENT_HPP_ | ||
| #define RCLCPP__GENERIC_CLIENT_HPP_ | ||
|
|
||
| #include <map> | ||
| #include <memory> | ||
| #include <future> | ||
| #include <string> | ||
| #include <vector> | ||
| #include <utility> | ||
fujitatomoya marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| #include "rcl/client.h" | ||
|
|
||
| #include "rclcpp/client.hpp" | ||
| #include "rclcpp/visibility_control.hpp" | ||
| #include "rcpputils/shared_library.hpp" | ||
fujitatomoya marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| #include "rosidl_typesupport_introspection_cpp/message_introspection.hpp" | ||
|
|
||
| namespace rclcpp | ||
| { | ||
| class GenericClient : public ClientBase | ||
| { | ||
| public: | ||
| using Request = void *; // Serialized data pointer of request message | ||
| using Response = void *; // Serialized data pointer of response message | ||
|
|
||
| using SharedResponse = std::shared_ptr<void>; | ||
|
|
||
| using Promise = std::promise<SharedResponse>; | ||
| using SharedPromise = std::shared_ptr<Promise>; | ||
|
|
||
| using Future = std::future<SharedResponse>; | ||
| using SharedFuture = std::shared_future<SharedResponse>; | ||
|
|
||
| RCLCPP_SMART_PTR_DEFINITIONS(GenericClient) | ||
|
|
||
| /// A convenient GenericClient::Future and request id pair. | ||
| /** | ||
| * Public members: | ||
| * - future: a std::future<void *>. | ||
| * - request_id: the request id associated with the future. | ||
| * | ||
| * All the other methods are equivalent to the ones std::future provides. | ||
| */ | ||
| struct FutureAndRequestId | ||
| : detail::FutureAndRequestId<Future> | ||
| { | ||
| using detail::FutureAndRequestId<Future>::FutureAndRequestId; | ||
|
|
||
| /// See std::future::share(). | ||
| SharedFuture share() noexcept {return this->future.share();} | ||
|
|
||
| /// Move constructor. | ||
| FutureAndRequestId(FutureAndRequestId && other) noexcept = default; | ||
| /// Deleted copy constructor, each instance is a unique owner of the future. | ||
| FutureAndRequestId(const FutureAndRequestId & other) = delete; | ||
| /// Move assignment. | ||
| FutureAndRequestId & operator=(FutureAndRequestId && other) noexcept = default; | ||
| /// Deleted copy assignment, each instance is a unique owner of the future. | ||
| FutureAndRequestId & operator=(const FutureAndRequestId & other) = delete; | ||
| /// Destructor. | ||
| ~FutureAndRequestId() = default; | ||
| }; | ||
|
|
||
| GenericClient( | ||
| rclcpp::node_interfaces::NodeBaseInterface * node_base, | ||
| rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph, | ||
| const std::string & service_name, | ||
| const std::string & service_type, | ||
| rcl_client_options_t & client_options); | ||
|
|
||
| RCLCPP_PUBLIC | ||
| SharedResponse | ||
| create_response() override; | ||
|
|
||
| RCLCPP_PUBLIC | ||
| std::shared_ptr<rmw_request_id_t> | ||
| create_request_header() override; | ||
|
|
||
| RCLCPP_PUBLIC | ||
| void | ||
| handle_response( | ||
| std::shared_ptr<rmw_request_id_t> request_header, | ||
| std::shared_ptr<void> response) override; | ||
|
|
||
| /// Send a request to the service server. | ||
| /** | ||
| * This method returns a `FutureAndRequestId` instance | ||
| * that can be passed to Executor::spin_until_future_complete() to | ||
| * wait until it has been completed. | ||
| * | ||
| * If the future never completes, | ||
| * e.g. the call to Executor::spin_until_future_complete() times out, | ||
| * GenericClient::remove_pending_request() must be called to clean the client internal state. | ||
| * Not doing so will make the `Client` instance to use more memory each time a response is not | ||
| * received from the service server. | ||
| * | ||
| * ```cpp | ||
| * auto future = client->async_send_request(my_request); | ||
| * if ( | ||
| * rclcpp::FutureReturnCode::TIMEOUT == | ||
| * executor->spin_until_future_complete(future, timeout)) | ||
| * { | ||
| * client->remove_pending_request(future); | ||
| * // handle timeout | ||
| * } else { | ||
| * handle_response(future.get()); | ||
| * } | ||
| * ``` | ||
| * | ||
| * \param[in] request request to be send. | ||
| * \return a FutureAndRequestId instance. | ||
| */ | ||
| RCLCPP_PUBLIC | ||
| FutureAndRequestId | ||
| async_send_request(const Request request); | ||
|
|
||
| /// Clean all pending requests older than a time_point. | ||
| /** | ||
| * \param[in] time_point Requests that were sent before this point are going to be removed. | ||
| * \param[inout] pruned_requests Removed requests id will be pushed to the vector | ||
| * if a pointer is provided. | ||
| * \return number of pending requests that were removed. | ||
| */ | ||
| template<typename AllocatorT = std::allocator<int64_t>> | ||
| size_t | ||
| prune_requests_older_than( | ||
| std::chrono::time_point<std::chrono::system_clock> time_point, | ||
| std::vector<int64_t, AllocatorT> * pruned_requests = nullptr) | ||
| { | ||
| return detail::prune_requests_older_than_impl( | ||
| pending_requests_, | ||
| pending_requests_mutex_, | ||
| time_point, | ||
| pruned_requests); | ||
| } | ||
|
|
||
| RCLCPP_PUBLIC | ||
| size_t | ||
| prune_pending_requests(); | ||
|
|
||
| RCLCPP_PUBLIC | ||
| bool | ||
| remove_pending_request( | ||
| int64_t request_id); | ||
|
|
||
| /// Take the next response for this client. | ||
| /** | ||
| * \sa ClientBase::take_type_erased_response(). | ||
| * | ||
| * \param[out] response_out The reference to a Service Response into | ||
| * which the middleware will copy the response being taken. | ||
| * \param[out] request_header_out The request header to be filled by the | ||
| * middleware when taking, and which can be used to associate the response | ||
| * to a specific request. | ||
| * \returns true if the response was taken, otherwise false. | ||
| * \throws rclcpp::exceptions::RCLError based exceptions if the underlying | ||
| * rcl function fail. | ||
| */ | ||
| RCLCPP_PUBLIC | ||
| bool | ||
| take_response(Response response_out, rmw_request_id_t & request_header_out) | ||
| { | ||
| return this->take_type_erased_response(response_out, request_header_out); | ||
| } | ||
|
|
||
| protected: | ||
| using CallbackInfoVariant = std::variant< | ||
| std::promise<SharedResponse>>; // Use variant for extension | ||
|
|
||
| int64_t | ||
| async_send_request_impl( | ||
| const Request request, | ||
| CallbackInfoVariant value); | ||
|
|
||
| std::optional<CallbackInfoVariant> | ||
| get_and_erase_pending_request( | ||
| int64_t request_number); | ||
|
|
||
| RCLCPP_DISABLE_COPY(GenericClient) | ||
|
|
||
| std::map<int64_t, std::pair< | ||
| std::chrono::time_point<std::chrono::system_clock>, | ||
| CallbackInfoVariant>> pending_requests_; | ||
| std::mutex pending_requests_mutex_; | ||
|
|
||
| private: | ||
| std::shared_ptr<rcpputils::SharedLibrary> ts_lib_; | ||
| const rosidl_typesupport_introspection_cpp::MessageMembers * response_members_; | ||
| }; | ||
| } // namespace rclcpp | ||
|
|
||
| #endif // RCLCPP__GENERIC_CLIENT_HPP_ | ||
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.