Skip to content

Commit

Permalink
- Implemented
Browse files Browse the repository at this point in the history
  - rcl_get_publishers_info_by_topic
  - rcl_get_subscriptions_info_by_topic
- Wrote tests for the same

Note: colcon build --packages-up-to rcl && colcon test --packages-select rcl && colcon test-result --verbose --test-result-base build/rcl
runs successfully without any errors or failures.

Signed-off-by: Jaison Titus <jaisontj92@gmail.com>
  • Loading branch information
jaisontj committed Nov 12, 2019
1 parent 80b79c7 commit 41c1a97
Show file tree
Hide file tree
Showing 3 changed files with 295 additions and 27 deletions.
69 changes: 42 additions & 27 deletions rcl/include/rcl/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,22 +525,23 @@ rcl_count_subscribers(
size_t * count);

/// Returns a list of all publishers to a topic.
/// Each element in the list will contain the publisher's name and its respective qos profile.
/// Each element in the list will contain the node name, node namespace, topic type,
/// gid and the qos profile of the publisher.
/**
* The `node` parameter must point to a valid node.
*
* The `topic_name` parameter must not be `NULL`.
*
* The `publishers` parameter must point to a valid struct of type rmw_participants_t.
* The `count` field inside the struct must be set to 0
* The `participants` field inside the struct must be set to null.
* The `publishers` parameter is the output for this function and will be set.
* The `no_mangle` parameter determines if the provided topic_name should be
* expanded to its fully qualified name.
*
* The topic name is not automatically remapped by this function.
* If there is a publisher created with topic name `foo` and remap rule `foo:=bar` then calling
* this with `topic_name` set to `bar` will return a list with 1 publisher, and with `topic_name` set to `foo`
* will return a list with 0 publishers.
* /sa rcl_remap_topic_name()
* It is the responsibility of the caller to ensure that `publishers_info` parameter points
* to a valid struct of type rmw_topic_info_array_t. The `count` field inside the struct
* must be set to 0 and the `info_array` field inside the struct must be set to null.
*
* The `allocator` will be used to allocate memory to the `info_array` member
* inside of `publishers_info`. However, it is the responsibility of the caller to
* reclaim any allocated resources to `publishers_info` to avoid leaking memory.
*
* <hr>
* Attribute | Adherence
Expand All @@ -552,38 +553,46 @@ rcl_count_subscribers(
* <i>[1] implementation may need to protect the data structure with a lock</i>
*
* \param[in] node the handle to the node being used to query the ROS graph
* \param[in] allocator allocator to be used when allocating space for
* the array inside publishers_info
* \param[in] topic_name the name of the topic in question
* \param[out] publishers a struct representing a list of publishers with their qos profile.
* \param[in] no_mangle if true, the topic_name will be expanded to its fully qualified name.
* \param[out] publishers_info a struct representing a list of publisher information.
* \return `RCL_RET_OK` if the query was successful, or
* \return `RCL_RET_NODE_INVALID` if the node is invalid, or
* \return `RCL_RET_INVALID_ARGUMENT` if any arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_get_qos_for_publishers(
rcl_get_publishers_info_by_topic(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
rmw_participants_t * publishers);
bool no_mangle,
rmw_topic_info_array_t * publishers_info);


/// Returns a list of all subscribers to a topic.
/// Each element in the list will contain the subscriber's name and its respective qos profile.
/// Returns a list of all subscriptions to a topic.
/// Each element in the list will contain the node name, node namespace, topic type,
/// gid and the qos profile of the subscription.
/**
* The `node` parameter must point to a valid node.
*
* The `topic_name` parameter must not be `NULL`.
*
* The `subscriber` parameter must point to a valid struct of type rmw_participants_t.
* The `count` field inside the struct must be set to 0
* The `participants` field inside the struct must be set to null.
* The `subscribers` parameter is the output for this function and will be set.
* The `no_mangle` parameter determines if the provided topic_name should be
* expanded to its fully qualified name.
*
* The topic name is not automatically remapped by this function.
* If there is a subscriber created with topic name `foo` and remap rule `foo:=bar` then calling
* this with `topic_name` set to `bar` will return a list with 1 subscriber , and with `topic_name` set to `foo`
* will return a list with 0 subscribers.
* /sa rcl_remap_topic_name()
* It is the responsibility of the caller to ensure that `subscriptions_info` parameter points
* to a valid struct of type rmw_topic_info_array_t. The `count` field inside the struct
* must be set to 0 and the `info_array` field inside the struct must be set to null.
*
* The `allocator` will be used to allocate memory to the `info_array` member
* inside of `subscriptions_info`.However, it is the responsibility of the caller to
* reclaim any allocated resources to `subscriptions_info` to avoid leaking memory.
*
* <hr>
* Attribute | Adherence
Expand All @@ -595,20 +604,26 @@ rcl_get_qos_for_publishers(
* <i>[1] implementation may need to protect the data structure with a lock</i>
*
* \param[in] node the handle to the node being used to query the ROS graph
* \param[in] allocator allocator to be used when allocating space for
* the array inside publishers_info
* \param[in] topic_name the name of the topic in question
* \param[out] subscribers a struct representing a list of subscribers with their qos profile.
* \param[in] no_mangle if true, the topic_name will be expanded to its fully qualified name.
* \param[out] subscriptions_info a struct representing a list of subscriptions information.
* \return `RCL_RET_OK` if the query was successful, or
* \return `RCL_RET_NODE_INVALID` if the node is invalid, or
* \return `RCL_RET_INVALID_ARGUMENT` if any arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if memory allocation fails, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_get_qos_for_subscribers(
rcl_get_subscriptions_info_by_topic(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
rmw_participants_t * subscribers);
bool no_mangle,
rmw_topic_info_array_t * subscriptions_info);


/// Check if a service server is available for the given service client.
Expand Down
76 changes: 76 additions & 0 deletions rcl/src/rcl/graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extern "C"
#include "rmw/get_topic_names_and_types.h"
#include "rmw/names_and_types.h"
#include "rmw/rmw.h"
#include "rmw/topic_info_array.h"
#include "rmw/validate_namespace.h"
#include "rmw/validate_node_name.h"

Expand Down Expand Up @@ -375,6 +376,81 @@ rcl_count_subscribers(
return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
}


typedef rmw_ret_t (* get_topic_info_func)(
const rmw_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
bool no_mangle,
rmw_topic_info_array_t * info_array);

rcl_ret_t
__rcl_get_info_by_topic(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
bool no_mangle,
rmw_topic_info_array_t * info_array,
get_topic_info_func get_topic_info)
{
if (!rcl_node_is_valid(node)) {
RCL_SET_ERROR_MSG("Invalid node provided.");
return RCL_RET_NODE_INVALID;
}
const rcl_node_options_t * node_options = rcl_node_get_options(node);
if (!node_options) {
RCL_SET_ERROR_MSG("Node options are invalid.");
return RCL_RET_NODE_INVALID; // shouldn't happen, but error is already set if so
}
RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT);
rcl_ret_t rcl_ret = rcl_convert_rmw_ret_to_rcl_ret(rmw_topic_info_array_check_zero(info_array));
if (rcl_ret != RCL_RET_OK) {
RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"rmw_topic_info_array_t must be zero initialized: %s,\n"
"Use rmw_get_zero_initialized_topic_info_array",
rmw_get_error_string().str);
rmw_reset_error();
return rcl_ret;
}
rmw_ret_t rmw_ret = get_topic_info(
rcl_node_get_rmw_handle(node),
allocator,
topic_name,
no_mangle,
info_array);
rcl_ret = rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
if (rcl_ret != RCL_RET_OK) {
RCL_SET_ERROR_MSG(rmw_get_error_string().str);
rmw_reset_error();
}
return rcl_ret;
}

rcl_ret_t
rcl_get_publishers_info_by_topic(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
bool no_mangle,
rmw_topic_info_array_t * publishers_info)
{
return __rcl_get_info_by_topic(node, allocator, topic_name, no_mangle, publishers_info,
rmw_get_publishers_info_by_topic);
}

rcl_ret_t
rcl_get_subscriptions_info_by_topic(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
bool no_mangle,
rmw_topic_info_array_t * subscriptions_info)
{
return __rcl_get_info_by_topic(node, allocator, topic_name, no_mangle, subscriptions_info,
rmw_get_subscriptions_info_by_topic);
}

rcl_ret_t
rcl_service_server_is_available(
const rcl_node_t * node,
Expand Down
Loading

0 comments on commit 41c1a97

Please sign in to comment.