23 #include "rcl/error_handling.h"
25 #include "rcl/node_type_cache.h"
26 #include "rcutils/logging_macros.h"
27 #include "rcutils/macros.h"
30 #include "rmw/error_handling.h"
31 #include "tracetools/tracetools.h"
34 #include "./publisher_impl.h"
41 return null_publisher;
48 const rosidl_message_type_support_t * type_support,
49 const char * topic_name,
68 if (publisher->
impl) {
69 RCL_SET_ERROR_MSG(
"publisher already initialized, or memory was unintialized");
77 RCUTILS_LOG_DEBUG_NAMED(
78 ROS_PACKAGE_NAME,
"Initializing publisher for topic name '%s'", topic_name);
81 char * remapped_topic_name = NULL;
88 &remapped_topic_name);
97 RCUTILS_LOG_DEBUG_NAMED(
98 ROS_PACKAGE_NAME,
"Expanded and remapped topic name '%s'", remapped_topic_name);
103 RCL_CHECK_FOR_NULL_WITH_MSG(
109 publisher->
impl->rmw_handle = rmw_create_publisher(
115 RCL_CHECK_FOR_NULL_WITH_MSG(
116 publisher->
impl->rmw_handle, rmw_get_error_string().str,
goto fail);
118 rmw_ret_t rmw_ret = rmw_publisher_get_actual_qos(
119 publisher->
impl->rmw_handle,
120 &publisher->
impl->actual_qos);
121 if (RMW_RET_OK != rmw_ret) {
122 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
125 publisher->
impl->actual_qos.avoid_ros_namespace_conventions =
126 options->
qos.avoid_ros_namespace_conventions;
128 publisher->
impl->options = *options;
130 if (
RCL_RET_OK != rcl_node_type_cache_register_type(
131 node, type_support->get_type_hash_func(type_support),
132 type_support->get_type_description_func(type_support),
133 type_support->get_type_description_sources_func(type_support)))
135 rcutils_reset_error();
136 RCL_SET_ERROR_MSG(
"Failed to register type for subscription");
139 publisher->
impl->type_hash = *type_support->get_type_hash_func(type_support);
141 RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME,
"Publisher initialized");
144 TRACETOOLS_TRACEPOINT(
146 (
const void *)publisher,
148 (
const void *)publisher->
impl->rmw_handle,
154 if (publisher->
impl) {
155 if (publisher->
impl->rmw_handle) {
156 rmw_ret_t rmw_fail_ret = rmw_destroy_publisher(
158 if (RMW_RET_OK != rmw_fail_ret) {
159 RCUTILS_SAFE_FWRITE_TO_STDERR(rmw_get_error_string().str);
160 RCUTILS_SAFE_FWRITE_TO_STDERR(
"\n");
164 allocator->deallocate(publisher->
impl, allocator->state);
165 publisher->
impl = NULL;
171 allocator->deallocate(remapped_topic_name, allocator->state);
189 RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME,
"Finalizing publisher");
190 if (publisher->
impl) {
197 rmw_destroy_publisher(rmw_node, publisher->
impl->rmw_handle);
198 if (ret != RMW_RET_OK) {
199 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
203 ROSIDL_TYPE_HASH_VERSION_UNSET != publisher->
impl->type_hash.version &&
204 RCL_RET_OK != rcl_node_type_cache_unregister_type(node, &publisher->
impl->type_hash))
206 RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
209 allocator.deallocate(publisher->
impl, allocator.state);
210 publisher->
impl = NULL;
212 RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME,
"Publisher finalized");
222 default_options.
qos = rmw_qos_profile_default;
227 bool disable_loaned_message =
false;
232 RCUTILS_SAFE_FWRITE_TO_STDERR(
"Failed to get disable_loaned_message: ");
233 RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
238 return default_options;
244 const rosidl_message_type_support_t * type_support,
250 return rcl_convert_rmw_ret_to_rcl_ret(
251 rmw_borrow_loaned_message(publisher->
impl->rmw_handle, type_support, ros_message));
257 void * loaned_message)
263 return rcl_convert_rmw_ret_to_rcl_ret(
264 rmw_return_loaned_message_from_publisher(publisher->
impl->rmw_handle, loaned_message));
270 const void * ros_message,
271 rmw_publisher_allocation_t * allocation)
280 TRACETOOLS_TRACEPOINT(
rcl_publish, (
const void *)publisher, (
const void *)ros_message);
281 if (rmw_publish(publisher->
impl->rmw_handle, ros_message, allocation) != RMW_RET_OK) {
282 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
292 rmw_publisher_allocation_t * allocation)
298 TRACETOOLS_TRACEPOINT(
rcl_publish, (
const void *)publisher, (
const void *)serialized_message);
299 rmw_ret_t ret = rmw_publish_serialized_message(
300 publisher->
impl->rmw_handle, serialized_message, allocation);
301 if (ret != RMW_RET_OK) {
302 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
303 if (ret == RMW_RET_BAD_ALLOC) {
315 rmw_publisher_allocation_t * allocation)
321 TRACETOOLS_TRACEPOINT(
rcl_publish, (
const void *)publisher, (
const void *)ros_message);
322 rmw_ret_t ret = rmw_publish_loaned_message(publisher->
impl->rmw_handle, ros_message, allocation);
323 if (ret != RMW_RET_OK) {
324 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
336 if (rmw_publisher_assert_liveliness(publisher->
impl->rmw_handle) != RMW_RET_OK) {
337 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
350 rmw_time_t rmw_timeout;
353 rmw_timeout.nsec = timeout % 1000000000;
354 }
else if (timeout < 0) {
355 rmw_time_t infinite = RMW_DURATION_INFINITE;
356 rmw_timeout = infinite;
358 rmw_time_t zero = RMW_DURATION_UNSPECIFIED;
362 rmw_ret_t ret = rmw_publisher_wait_for_all_acked(publisher->
impl->rmw_handle, rmw_timeout);
363 if (ret != RMW_RET_OK) {
364 if (ret == RMW_RET_TIMEOUT) {
367 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
368 if (ret == RMW_RET_UNSUPPORTED) {
384 return publisher->
impl->rmw_handle->topic_name;
393 return &publisher->
impl->options;
402 return publisher->
impl->rmw_handle;
411 return publisher->
impl->context;
421 if (!rcl_error_is_set()) {
424 RCL_SET_ERROR_MSG(
"publisher's context is invalid");
428 RCL_CHECK_FOR_NULL_WITH_MSG(
429 publisher->
impl->rmw_handle,
"publisher's rmw handle is invalid",
return false);
436 RCL_CHECK_FOR_NULL_WITH_MSG(publisher,
"publisher pointer is invalid",
return false);
437 RCL_CHECK_FOR_NULL_WITH_MSG(
438 publisher->
impl,
"publisher implementation is invalid",
return false);
439 RCL_CHECK_FOR_NULL_WITH_MSG(
440 publisher->
impl->rmw_handle,
"publisher's rmw handle is invalid",
return false);
447 size_t * subscription_count)
454 rmw_ret_t ret = rmw_publisher_count_matched_subscriptions(
455 publisher->
impl->rmw_handle, subscription_count);
457 if (ret != RMW_RET_OK) {
458 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
459 return rcl_convert_rmw_ret_to_rcl_ret(ret);
464 const rmw_qos_profile_t *
470 return &publisher->
impl->actual_qos;
484 return publisher->
impl->rmw_handle->can_loan_messages;
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
#define RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, msg, fail_statement)
Check that the given allocator is initialized, or fail with a message.
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
RCL_PUBLIC RCL_WARN_UNUSED bool rcl_context_is_valid(const rcl_context_t *context)
Return true if the given context is currently valid, otherwise false.
RCL_PUBLIC bool rcl_node_is_valid(const rcl_node_t *node)
Return true if the node is valid, else false.
RCL_PUBLIC rcl_ret_t rcl_get_disable_loaned_message(bool *disable_loaned_message)
Check if loaned message is disabled, according to the environment variable.
RCL_PUBLIC RCL_WARN_UNUSED rmw_node_t * rcl_node_get_rmw_handle(const rcl_node_t *node)
Return the rmw node handle.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_resolve_name(const rcl_node_t *node, const char *input_name, rcl_allocator_t allocator, bool is_service, bool only_expand, char **output_name)
Expand a given name into a fully-qualified topic name and apply remapping rules.
RCL_PUBLIC bool rcl_node_is_valid_except_context(const rcl_node_t *node)
Return true if node is valid, except for the context being valid.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publisher_init(rcl_publisher_t *publisher, const rcl_node_t *node, const rosidl_message_type_support_t *type_support, const char *topic_name, const rcl_publisher_options_t *options)
Initialize a rcl publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publish_loaned_message(const rcl_publisher_t *publisher, void *ros_message, rmw_publisher_allocation_t *allocation)
Publish a loaned message on a topic using a publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publisher_wait_for_all_acked(const rcl_publisher_t *publisher, rcl_duration_value_t timeout)
Wait until all published message data is acknowledged or until the specified timeout elapses.
RCL_PUBLIC bool rcl_publisher_is_valid(const rcl_publisher_t *publisher)
Return true if the publisher is valid, otherwise false.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publish_serialized_message(const rcl_publisher_t *publisher, const rcl_serialized_message_t *serialized_message, rmw_publisher_allocation_t *allocation)
Publish a serialized message on a topic using a publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_context_t * rcl_publisher_get_context(const rcl_publisher_t *publisher)
Return the context associated with this publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publish(const rcl_publisher_t *publisher, const void *ros_message, rmw_publisher_allocation_t *allocation)
Publish a ROS message on a topic using a publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_borrow_loaned_message(const rcl_publisher_t *publisher, const rosidl_message_type_support_t *type_support, void **ros_message)
Borrow a loaned message.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publisher_get_subscription_count(const rcl_publisher_t *publisher, size_t *subscription_count)
Get the number of subscriptions matched to a publisher.
RCL_PUBLIC RCL_WARN_UNUSED rmw_publisher_t * rcl_publisher_get_rmw_handle(const rcl_publisher_t *publisher)
Return the rmw publisher handle.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_publisher_get_topic_name(const rcl_publisher_t *publisher)
Get the topic name for the publisher.
RCL_PUBLIC RCL_WARN_UNUSED const rmw_qos_profile_t * rcl_publisher_get_actual_qos(const rcl_publisher_t *publisher)
Get the actual qos settings of the publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_publisher_options_t rcl_publisher_get_default_options(void)
Return the default publisher options in a rcl_publisher_options_t.
RCL_PUBLIC bool rcl_publisher_is_valid_except_context(const rcl_publisher_t *publisher)
Return true if the publisher is valid except the context, otherwise false.
RCL_PUBLIC RCL_WARN_UNUSED const rcl_publisher_options_t * rcl_publisher_get_options(const rcl_publisher_t *publisher)
Return the rcl publisher options.
RCL_PUBLIC RCL_WARN_UNUSED rcl_publisher_t rcl_get_zero_initialized_publisher(void)
Return a rcl_publisher_t struct with members set to NULL.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publisher_fini(rcl_publisher_t *publisher, rcl_node_t *node)
Finalize a rcl_publisher_t.
RCL_PUBLIC bool rcl_publisher_can_loan_messages(const rcl_publisher_t *publisher)
Check if publisher instance can loan messages.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_return_loaned_message_from_publisher(const rcl_publisher_t *publisher, void *loaned_message)
Return a loaned message previously borrowed from a publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publisher_assert_liveliness(const rcl_publisher_t *publisher)
Manually assert that this Publisher is alive (for RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC)
Encapsulates the non-global state of an init/shutdown cycle.
Structure which encapsulates a ROS Node.
rcl_context_t * context
Context associated with this node.
Options available for a rcl publisher.
rmw_qos_profile_t qos
Middleware quality of service settings for the publisher.
rmw_publisher_options_t rmw_publisher_options
rmw specific publisher options, e.g. the rmw implementation specific payload.
bool disable_loaned_message
Disable flag to LoanedMessage, initialized via environmental variable.
rcl_allocator_t allocator
Custom allocator for the publisher, used for incidental allocations.
Structure which encapsulates a ROS Publisher.
rcl_publisher_impl_t * impl
Pointer to the publisher implementation.
#define RCL_NS_TO_S
Convenience macro to convert nanoseconds to seconds.
rcutils_duration_value_t rcl_duration_value_t
A duration of time, measured in nanoseconds.
#define RCL_RET_UNSUPPORTED
Unsupported return code.
#define RCL_RET_UNKNOWN_SUBSTITUTION
Topic name substitution is unknown.
#define RCL_RET_ALREADY_INIT
rcl_init() already called return code.
#define RCL_RET_OK
Success return code.
#define RCL_RET_BAD_ALLOC
Failed to allocate memory return code.
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
#define RCL_RET_ERROR
Unspecified error return code.
rmw_serialized_message_t rcl_serialized_message_t
typedef for rmw_serialized_message_t;
#define RCL_RET_NODE_INVALID
Invalid rcl_node_t given return code.
#define RCL_RET_TOPIC_NAME_INVALID
Topic name does not pass validation.
#define RCL_RET_TIMEOUT
Timeout occurred return code.
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
#define RCL_RET_PUBLISHER_INVALID
Invalid rcl_publisher_t given return code.