forked from ros2/rclcpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request ros2#30 from ros2/c_services
C clients/services
- Loading branch information
Showing
17 changed files
with
1,760 additions
and
23 deletions.
There are no files selected for viewing
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
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,301 @@ | ||
// Copyright 2016 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. | ||
|
||
#ifndef RCL__CLIENT_H_ | ||
#define RCL__CLIENT_H_ | ||
|
||
#if __cplusplus | ||
extern "C" | ||
{ | ||
#endif | ||
|
||
#include "rosidl_generator_c/service_type_support.h" | ||
|
||
#include "rcl/macros.h" | ||
#include "rcl/node.h" | ||
#include "rcl/visibility_control.h" | ||
|
||
/// Internal rcl client implementation struct. | ||
struct rcl_client_impl_t; | ||
|
||
/// Handle for a rcl client. | ||
typedef struct rcl_client_t | ||
{ | ||
struct rcl_client_impl_t * impl; | ||
} rcl_client_t; | ||
|
||
/// Options available for a rcl client. | ||
typedef struct rcl_client_options_t | ||
{ | ||
/// Middleware quality of service settings for the client. | ||
rmw_qos_profile_t qos; | ||
/// Custom allocator for the client, used for incidental allocations. | ||
/* For default behavior (malloc/free), use: rcl_get_default_allocator() */ | ||
rcl_allocator_t allocator; | ||
} rcl_client_options_t; | ||
|
||
/// Return a rcl_client_t struct with members set to NULL. | ||
/* Should be called to get a null rcl_client_t before passing to | ||
* rcl_initalize_client(). | ||
* It's also possible to use calloc() instead of this if the rcl_client is | ||
* being allocated on the heap. | ||
*/ | ||
RCL_PUBLIC | ||
RCL_WARN_UNUSED | ||
rcl_client_t | ||
rcl_get_zero_initialized_client(void); | ||
|
||
|
||
/// Initialize a rcl client. | ||
/* After calling this function on a rcl_client_t, it can be used to send requests of the given | ||
* type by calling rcl_send_request(). | ||
* If the request is received by a (possibly remote) service and if the service sends a response, | ||
* the client can access the response through rcl_take_response once the response is available to | ||
* the client. | ||
* | ||
* The given rcl_node_t must be valid and the resulting rcl_client_t is only | ||
* valid as long as the given rcl_node_t remains valid. | ||
* | ||
* The rosidl_service_type_support_t is obtained on a per .srv type basis. | ||
* When the user defines a ROS service, code is generated which provides the | ||
* required rosidl_service_type_support_t object. | ||
* This object can be obtained using a language appropriate mechanism. | ||
* \TODO(wjwwood) probably should talk about this once and link to it instead | ||
* For C this macro can be used (using example_interfaces/AddTwoInts as an example): | ||
* | ||
* #include <rosidl_generator_c/service_type_support.h> | ||
* #include <example_interfaces/srv/add_two_ints.h> | ||
* rosidl_service_type_support_t * ts = | ||
* ROSIDL_GET_SERVICE_TYPE_SUPPORT(example_interfaces, AddTwoInts); | ||
* | ||
* For C++ a template function is used: | ||
* | ||
* #include <rosidl_generator_cpp/service_type_support.hpp> | ||
* #include <example_interfaces/srv/add_two_ints.h> | ||
* rosidl_service_type_support_t * ts = rosidl_generator_cpp::get_service_type_support_handle< | ||
* example_interfaces::srv::AddTwoInts>(); | ||
* | ||
* The rosidl_service_type_support_t object contains service type specific | ||
* information used to send or take requests and responses. | ||
* | ||
* \TODO(wjwwood) update this once we've come up with an official scheme. | ||
* The service name must be a non-empty string which follows the topic/service naming | ||
* format. | ||
* | ||
* The options struct allows the user to set the quality of service settings as | ||
* well as a custom allocator which is used when initializing/finalizing the | ||
* client to allocate space for incidentals, e.g. the service name string. | ||
* | ||
* Expected usage (for C services): | ||
* | ||
* #include <rcl/rcl.h> | ||
* #include <rosidl_generator_c/service_type_support.h> | ||
* #include <example_interfaces/srv/add_two_ints.h> | ||
* | ||
* rcl_node_t node = rcl_get_zero_initialized_node(); | ||
* rcl_node_options_t node_ops = rcl_node_get_default_options(); | ||
* rcl_ret_t ret = rcl_node_init(&node, "node_name", &node_ops); | ||
* // ... error handling | ||
* rosidl_service_type_support_t * ts = ROSIDL_GET_SERVICE_TYPE_SUPPORT( | ||
* example_interfaces, AddTwoInts); | ||
* rcl_client_t client = rcl_get_zero_initialized_client(); | ||
* rcl_client_options_t client_ops = rcl_client_get_default_options(); | ||
* ret = rcl_client_init(&client, &node, ts, "add_two_ints", &client_ops); | ||
* // ... error handling, and on shutdown do finalization: | ||
* ret = rcl_client_fini(&client, &node); | ||
* // ... error handling for rcl_client_fini() | ||
* ret = rcl_node_fini(&node); | ||
* // ... error handling for rcl_node_fini() | ||
* | ||
* This function is not thread-safe. | ||
* | ||
* \param[inout] client preallocated client structure | ||
* \param[in] node valid rcl node handle | ||
* \param[in] type_support type support object for the service's type | ||
* \param[in] service_name the name of the service to request | ||
* \param[in] options client options, including quality of service settings | ||
* \return RCL_RET_OK if the client was initialized successfully, or | ||
* RCL_RET_NODE_INVALID if the node is invalid, or | ||
* RCL_RET_ALREADY_INIT if the client is already initialized, or | ||
* RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or | ||
* RCL_RET_BAD_ALLOC if allocating memory fails, or | ||
* RCL_RET_ERROR if an unspecified error occurs. | ||
*/ | ||
RCL_PUBLIC | ||
RCL_WARN_UNUSED | ||
rcl_ret_t | ||
rcl_client_init( | ||
rcl_client_t * client, | ||
const rcl_node_t * node, | ||
const rosidl_service_type_support_t * type_support, | ||
const char * service_name, | ||
const rcl_client_options_t * options); | ||
|
||
/// Finalize a rcl_client_t. | ||
/* | ||
* After calling, calls to rcl_send_request and rcl_take_response will fail when using this client. | ||
* However, the given node handle is still valid. | ||
* | ||
* This function is not thread-safe. | ||
* | ||
* \param[inout] client handle to the client to be finalized | ||
* \param[in] node handle to the node used to create the client | ||
* \return RCL_RET_OK if client was finalized successfully, or | ||
* RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or | ||
* RCL_RET_ERROR if an unspecified error occurs. | ||
*/ | ||
RCL_PUBLIC | ||
RCL_WARN_UNUSED | ||
rcl_ret_t | ||
rcl_client_fini(rcl_client_t * client, rcl_node_t * node); | ||
|
||
/// Return the default client options in a rcl_client_options_t. | ||
RCL_PUBLIC | ||
RCL_WARN_UNUSED | ||
rcl_client_options_t | ||
rcl_client_get_default_options(void); | ||
|
||
/// Send a ROS request using a client. | ||
/* It is the job of the caller to ensure that the type of the ros_request | ||
* parameter and the type associate with the client (via the type support) | ||
* match. | ||
* Passing a different type to send_request produces undefined behavior and cannot | ||
* be checked by this function and therefore no deliberate error will occur. | ||
* | ||
* send_request is an non-blocking call. | ||
* | ||
* The ROS request message given by the ros_request void pointer is always owned by the | ||
* calling code, but should remain constant during send_request. | ||
* | ||
* This function is thread safe so long as access to both the client and the | ||
* ros_request is synchronized. | ||
* That means that calling rcl_send_request from multiple threads is allowed, but | ||
* calling rcl_send_request at the same time as non-thread safe client functions | ||
* is not, e.g. calling rcl_send_request and rcl_client_fini concurrently | ||
* is not allowed. | ||
* Before calling rcl_send_request the message can change and after calling | ||
* rcl_send_request the message can change, but it cannot be changed during the | ||
* send_request call. | ||
* The same ros_request, however, can be passed to multiple calls of | ||
* rcl_send_request simultaneously, even if the clients differ. | ||
* The ros_request is unmodified by rcl_send_request. | ||
* | ||
* \param[in] client handle to the client which will make the response | ||
* \param[in] ros_request type-erased pointer to the ROS request message | ||
* \param[out] sequence_number the sequence number | ||
* \return RCL_RET_OK if the request was sent successfully, or | ||
* RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or | ||
* RCL_RET_CLIENT_INVALID if the client is invalid, or | ||
* RCL_RET_ERROR if an unspecified error occurs. | ||
*/ | ||
RCL_PUBLIC | ||
RCL_WARN_UNUSED | ||
rcl_ret_t | ||
rcl_send_request(const rcl_client_t * client, const void * ros_request, int64_t * sequence_number); | ||
|
||
|
||
// Take a ROS response using a client | ||
/* It is the job of the caller to ensure that the type of the ros_response | ||
* parameter and the type associate with the client (via the type support) | ||
* match. | ||
* Passing a different type to take_response produces undefined behavior and cannot | ||
* be checked by this function and therefore no deliberate error will occur. | ||
* The request_header is an rmw struct for meta-information about the request sent | ||
* (e.g. the sequence number). | ||
* ros_response should point to an already allocated ROS response message struct of the | ||
* correct type, into which the response from the service will be copied. | ||
* | ||
* \param[in] client handle to the client which will take the response | ||
* \param[inout] request_header pointer to the request header | ||
* \param[inout] ros_response type-erased pointer to the ROS response message | ||
* \return RCL_RET_OK if the response was taken successfully, or | ||
* RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or | ||
* RCL_RET_CLIENT_INVALID if the client is invalid, or | ||
* RCL_RET_ERROR if an unspecified error occurs. | ||
*/ | ||
RCL_PUBLIC | ||
RCL_WARN_UNUSED | ||
rcl_ret_t | ||
rcl_take_response( | ||
const rcl_client_t * client, | ||
rmw_request_id_t * request_header, | ||
void * ros_response); | ||
|
||
/// Get the name of the service that this client will request a response from. | ||
/* This function returns the client's internal service name string. | ||
* This function can fail, and therefore return NULL, if the: | ||
* - client is NULL | ||
* - client is invalid (never called init, called fini, or invalid node) | ||
* | ||
* The returned string is only valid as long as the rcl_client_t is valid. | ||
* The value of the string may change if the service name changes, and therefore | ||
* copying the string is recommended if this is a concern. | ||
* | ||
* This function is not thread-safe, and copying the result is not thread-safe. | ||
* | ||
* \param[in] client pointer to the client | ||
* \return name string if successful, otherwise NULL | ||
*/ | ||
RCL_PUBLIC | ||
RCL_WARN_UNUSED | ||
const char * | ||
rcl_client_get_service_name(const rcl_client_t * client); | ||
|
||
/// Return the rcl client options. | ||
/* This function returns the client's internal options struct. | ||
* This function can fail, and therefore return NULL, if the: | ||
* - client is NULL | ||
* - client is invalid (never called init, called fini, or invalid node) | ||
* | ||
* The returned struct is only valid as long as the rcl_client_t is valid. | ||
* The values in the struct may change if the options of the client change, | ||
* and therefore copying the struct is recommended if this is a concern. | ||
* | ||
* This function is not thread-safe, and copying the result is not thread-safe. | ||
* | ||
* \param[in] client pointer to the client | ||
* \return options struct if successful, otherwise NULL | ||
*/ | ||
RCL_PUBLIC | ||
RCL_WARN_UNUSED | ||
const rcl_client_options_t * | ||
rcl_client_get_options(const rcl_client_t * client); | ||
|
||
/// Return the rmw client handle. | ||
/* The handle returned is a pointer to the internally held rmw handle. | ||
* This function can fail, and therefore return NULL, if the: | ||
* - client is NULL | ||
* - client is invalid (never called init, called fini, or invalid node) | ||
* | ||
* The returned handle is made invalid if the client is finalized or if | ||
* rcl_shutdown() is called. | ||
* The returned handle is not guaranteed to be valid for the life time of the | ||
* client as it may be finalized and recreated itself. | ||
* Therefore it is recommended to get the handle from the client using | ||
* this function each time it is needed and avoid use of the handle | ||
* concurrently with functions that might change it. | ||
* | ||
* \param[in] client pointer to the rcl client | ||
* \return rmw client handle if successful, otherwise NULL | ||
*/ | ||
RCL_PUBLIC | ||
RCL_WARN_UNUSED | ||
rmw_client_t * | ||
rcl_client_get_rmw_handle(const rcl_client_t * client); | ||
|
||
#if __cplusplus | ||
} | ||
#endif | ||
|
||
#endif // RCL__CLIENT_H_ |
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
Oops, something went wrong.