Skip to content

Commit a4633b8

Browse files
authored
Add ~/get_type_description service (rep2011) (#1052)
* Add ~/get_type_description service API * Add node type cache * Register subscription, publication, service and action types with node type cache * Add functions to convert between rosidl_runtime_c / type_description_interfaces structs RCL does not initialize the get_type_description service itself, instead providing a full enough API for full language clients to initialize it and register its callback within their threading/execution framework Signed-off-by: Hans-Joachim Krauch <[email protected]> Signed-off-by: Emerson Knapp <[email protected]>
1 parent 43f8163 commit a4633b8

24 files changed

+2001
-24
lines changed

rcl/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ set(${PROJECT_NAME}_sources
5959
src/rcl/network_flow_endpoints.c
6060
src/rcl/node.c
6161
src/rcl/node_options.c
62+
src/rcl/node_type_cache.c
6263
src/rcl/publisher.c
6364
src/rcl/remap.c
6465
src/rcl/node_resolve_name.c
@@ -70,6 +71,7 @@ set(${PROJECT_NAME}_sources
7071
src/rcl/time.c
7172
src/rcl/timer.c
7273
src/rcl/type_hash.c
74+
src/rcl/type_description_conversions.c
7375
src/rcl/validate_enclave_name.c
7476
src/rcl/validate_topic_name.c
7577
src/rcl/wait.c

rcl/include/rcl/node.h

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ extern "C"
3333
#include "rcl/types.h"
3434
#include "rcl/visibility_control.h"
3535

36+
#include "type_description_interfaces/srv/get_type_description.h"
37+
3638
extern const char * const RCL_DISABLE_LOANED_MESSAGES_ENV_VAR;
3739

3840
typedef struct rcl_node_impl_s rcl_node_impl_t;
41+
typedef struct rcl_service_s rcl_service_t;
3942

4043
/// Structure which encapsulates a ROS Node.
4144
typedef struct rcl_node_s
@@ -549,6 +552,115 @@ RCL_PUBLIC
549552
rcl_ret_t
550553
rcl_get_disable_loaned_message(bool * disable_loaned_message);
551554

555+
/// Initialize the node's ~/get_type_description service.
556+
/**
557+
* This function initializes the node's ~/get_type_description service
558+
* which can be used to retrieve information about types used by the node's
559+
* publishers, subscribers, services or actions.
560+
*
561+
* Note that this will not register any callback for the service, client-level code
562+
* must register rcl_node_type_description_service_handle_request or a custom callback
563+
* to handle incoming requests, via that client's executor/waitset capabilities.
564+
*
565+
* This will initialize the node's type cache, if it has not been initialized already.
566+
*
567+
* <hr>
568+
* Attribute | Adherence
569+
* ------------------ | -------------
570+
* Allocates Memory | Yes
571+
* Thread-Safe | No
572+
* Uses Atomics | No
573+
* Lock-Free | Yes
574+
*
575+
* \param[in] node handle to the node for which to initialize the service
576+
* \return #RCL_RET_OK if the service was successfully initialized, or
577+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
578+
* \return #RCL_RET_ALREADY_INIT if the service is already initialized, or
579+
* \return #RCL_RET_BAD_ALLOC if memory allocation for the service failed, or
580+
* \return #RCL_RET_ERROR if an unspecified error occurs.
581+
*/
582+
RCL_PUBLIC
583+
RCL_WARN_UNUSED
584+
rcl_ret_t rcl_node_type_description_service_init(rcl_node_t * node);
585+
586+
/// Finalizes the node's ~/get_type_description service.
587+
/**
588+
* This function finalizes the node's private ~/get_type_description service.
589+
*
590+
* <hr>
591+
* Attribute | Adherence
592+
* ------------------ | -------------
593+
* Allocates Memory | No
594+
* Thread-Safe | No
595+
* Uses Atomics | No
596+
* Lock-Free | Yes
597+
*
598+
* \param[in] node the handle to the node whose type cache should be initialized
599+
* \return #RCL_RET_OK if service was deinitialized successfully, or
600+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
601+
* \return #RCL_RET_SERVICE_INVALID if the service is invalid, or
602+
* \return #RCL_RET_NODE_INVALID if the node is invalid, or
603+
* \return #RCL_RET_ERROR if an unspecified error occurs.
604+
*/
605+
RCL_PUBLIC
606+
RCL_WARN_UNUSED
607+
rcl_ret_t rcl_node_type_description_service_fini(rcl_node_t * node);
608+
609+
610+
/// Returns a pointer to the node's ~/get_type_description service.
611+
/**
612+
* On success, sets service_out to the initialized service.
613+
* rcl_node_type_description_service_init must be called before this.
614+
*
615+
* <hr>
616+
* Attribute | Adherence
617+
* ------------------ | -------------
618+
* Allocates Memory | No
619+
* Thread-Safe | No
620+
* Uses Atomics | No
621+
* Lock-Free | Yes
622+
*
623+
* \param[in] node the handle to the node
624+
* \param[out] service_out Handle to pointer that will be set
625+
* \return #RCL_RET_OK if valid service was returned successfully, or
626+
* \return #RCL_RET_NODE_INVALID if node is invalid, or
627+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
628+
* \return #RCL_RET_NOT_INIT if the service hasn't yet been initialized, or
629+
* \return #RCL_RET_ERROR if an unspecified error occurs.
630+
*/
631+
RCL_PUBLIC
632+
RCL_WARN_UNUSED
633+
rcl_ret_t rcl_node_get_type_description_service(
634+
const rcl_node_t * node,
635+
rcl_service_t ** service_out);
636+
637+
638+
/// Process a single pending request to the GetTypeDescription service.
639+
/**
640+
* This function may be called to handle incoming requests by any client starting the service.
641+
* It is not intended to be called directly by users.
642+
*
643+
* <hr>
644+
* Attribute | Adherence
645+
* ------------------ | -------------
646+
* Allocates Memory | No
647+
* Thread-Safe | No
648+
* Uses Atomics | No
649+
* Lock-Free | Yes
650+
*
651+
* \param[in] node the handle to the node
652+
* \param[in] request_header ID of the incoming request
653+
* \param[in] request Request that came in to the service
654+
* \param[out] response Allocated, uninitialized response to the request
655+
* \return void
656+
*/
657+
RCL_PUBLIC
658+
void rcl_node_type_description_service_handle_request(
659+
rcl_node_t * node,
660+
const rmw_request_id_t * request_header,
661+
const type_description_interfaces__srv__GetTypeDescription_Request * request,
662+
type_description_interfaces__srv__GetTypeDescription_Response * response);
663+
552664
#ifdef __cplusplus
553665
}
554666
#endif

rcl/include/rcl/node_options.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,6 @@ typedef struct rcl_node_options_s
5454

5555
/// Middleware quality of service settings for /rosout.
5656
rmw_qos_profile_t rosout_qos;
57-
58-
/// Register the ~/get_type_description service. Defaults to false.
59-
bool enable_type_description_service;
6057
} rcl_node_options_t;
6158

6259
/// Return the default node options in a rcl_node_options_t.

rcl/include/rcl/node_type_cache.h

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// Copyright 2023 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef RCL__NODE_TYPE_CACHE_H_
16+
#define RCL__NODE_TYPE_CACHE_H_
17+
18+
#include "rcl/node.h"
19+
#include "rcl/types.h"
20+
#include "rcl/visibility_control.h"
21+
#include "rosidl_runtime_c/type_description/type_description__struct.h"
22+
#include "rosidl_runtime_c/type_description/type_source__struct.h"
23+
#include "type_description_interfaces/msg/type_description.h"
24+
#include "type_description_interfaces/msg/type_source.h"
25+
26+
#ifdef __cplusplus
27+
extern "C" {
28+
#endif
29+
30+
typedef struct rcl_type_info_t
31+
{
32+
type_description_interfaces__msg__TypeDescription * type_description;
33+
type_description_interfaces__msg__TypeSource__Sequence * type_sources;
34+
} rcl_type_info_t;
35+
36+
/// Initialize the node's type cache.
37+
/**
38+
* This function initializes hash map of the node's type cache such that types
39+
* can be registered and retrieved.
40+
* Note that to correctly capture all types used by a node, this needs to be called
41+
* before any "builtin" publishers or services are created.
42+
*
43+
* <hr>
44+
* Attribute | Adherence
45+
* ------------------ | -------------
46+
* Allocates Memory | Yes
47+
* Thread-Safe | No
48+
* Uses Atomics | No
49+
* Lock-Free | Yes
50+
*
51+
* \param[in] node the handle to the node whose type cache should be initialized
52+
* \return #RCL_RET_OK if the node's type cache was successfully initialized, or
53+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
54+
* \return #RCL_RET_NODE_INVALID if the given `node` is invalid, or
55+
* \return #RCL_RET_ERROR if an unspecified error occurs.
56+
*/
57+
RCL_WARN_UNUSED
58+
rcl_ret_t rcl_node_type_cache_init(rcl_node_t * node);
59+
60+
/// Finalize the node's type cache.
61+
/**
62+
* This function clears the hash map of the node's type cache and deallocates
63+
* used memory.
64+
*
65+
* <hr>
66+
* Attribute | Adherence
67+
* ------------------ | -------------
68+
* Allocates Memory | No
69+
* Thread-Safe | No
70+
* Uses Atomics | No
71+
* Lock-Free | Yes
72+
*
73+
* \param[in] node the handle to the node whose type cache should be finalized
74+
* \return #RCL_RET_OK if the node's type cache was successfully finalized, or
75+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
76+
* \return #RCL_RET_NODE_INVALID if the given `node` is invalid, or
77+
* \return #RCL_RET_ERROR if an unspecified error occurs.
78+
*/
79+
RCL_WARN_UNUSED
80+
rcl_ret_t rcl_node_type_cache_fini(rcl_node_t * node);
81+
82+
/// Register a type with the node's type cache.
83+
/**
84+
* This function registers the given type, uniquely identified by the type_hash,
85+
* with the node with the node's type cache. Multiple registrations of the same
86+
* type will increment its registration count.
87+
*
88+
* <hr>
89+
* Attribute | Adherence
90+
* ------------------ | -------------
91+
* Allocates Memory | Yes
92+
* Thread-Safe | No
93+
* Uses Atomics | No
94+
* Lock-Free | Yes
95+
*
96+
* \param[in] node the handle to the node whose type cache should be finalized
97+
* \param[in] type_hash hash of the type
98+
* \param[in] type_description type description struct
99+
* \param[in] type_description_sources type description sources struct
100+
* \return #RCL_RET_OK if the type was successfully registered, or
101+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
102+
* \return #RCL_RET_NODE_INVALID if the given `node` is invalid, or
103+
* \return #RCL_RET_ERROR if an unspecified error occurs.
104+
*/
105+
RCL_PUBLIC
106+
RCL_WARN_UNUSED
107+
rcl_ret_t rcl_node_type_cache_register_type(
108+
const rcl_node_t * node, const rosidl_type_hash_t * type_hash,
109+
const rosidl_runtime_c__type_description__TypeDescription * type_description,
110+
const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources
111+
);
112+
113+
/// Unregister a message type from the node's type cache.
114+
/**
115+
* This function uses the given `type_hash` to unregister the associated type in
116+
* the node's type cache. If the type has been registered multiple times, the
117+
* type will only be removed if its registration count reaches 0.
118+
*
119+
* <hr>
120+
* Attribute | Adherence
121+
* ------------------ | -------------
122+
* Allocates Memory | Yes
123+
* Thread-Safe | No
124+
* Uses Atomics | No
125+
* Lock-Free | Yes
126+
*
127+
* \param[in] node the handle to the node whose type cache should be finalized
128+
* \param[in] type_hash type hash
129+
* \return #RCL_RET_OK if the type was successfully registered, or
130+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
131+
* \return #RCL_RET_NODE_INVALID if the given `node` is invalid, or
132+
* \return #RCL_RET_ERROR if an unspecified error occurs.
133+
*/
134+
RCL_PUBLIC
135+
RCL_WARN_UNUSED
136+
rcl_ret_t rcl_node_type_cache_unregister_type(
137+
const rcl_node_t * node, const rosidl_type_hash_t * type_hash);
138+
139+
/// Retrieve type information from the node's type cache.
140+
/**
141+
* This function returns the desired type information from the node's type cache
142+
*
143+
* The `type_info` field must point to an allocated `rcl_type_info_t` object to
144+
* which the type information will be written.
145+
*
146+
* <hr>
147+
* Attribute | Adherence
148+
* ------------------ | -------------
149+
* Allocates Memory | No
150+
* Thread-Safe | No
151+
* Uses Atomics | No
152+
* Lock-Free | Yes
153+
*
154+
* \param[in] node the handle to the node whose type cache should be queried
155+
* \param[in] type_hash type hash
156+
* \param[out] type_info pointer to the type info struct that will be populated
157+
* \return #RCL_RET_OK if type information was retrieved successfully
158+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
159+
* \return #RCL_RET_NODE_INVALID if the given `node` is invalid, or
160+
* \return #RCL_RET_NOT_INIT if node's type cache has not been initialized, or
161+
* \return #RCL_RET_ERROR if an unspecified error occurs.
162+
*/
163+
RCL_PUBLIC
164+
RCL_WARN_UNUSED
165+
rcl_ret_t rcl_node_type_cache_get_type_info(
166+
const rcl_node_t * node,
167+
const rosidl_type_hash_t * type_hash,
168+
rcl_type_info_t * type_info);
169+
170+
#ifdef __cplusplus
171+
}
172+
#endif
173+
174+
#endif // RCL__NODE_TYPE_CACHE_H_

0 commit comments

Comments
 (0)