26 #include "rcl/error_handling.h"
28 #include "rcl/node_type_cache.h"
29 #include "rcutils/logging_macros.h"
30 #include "rcutils/macros.h"
33 #include "rmw/error_handling.h"
34 #include "tracetools/tracetools.h"
37 #include "./publisher_impl.h"
44 return null_publisher;
51 const rosidl_message_type_support_t * type_support,
52 const char * topic_name,
71 if (publisher->
impl) {
72 RCL_SET_ERROR_MSG(
"publisher already initialized, or memory was unintialized");
80 RCUTILS_LOG_DEBUG_NAMED(
81 ROS_PACKAGE_NAME,
"Initializing publisher for topic name '%s'", topic_name);
84 char * remapped_topic_name = NULL;
91 &remapped_topic_name);
100 RCUTILS_LOG_DEBUG_NAMED(
101 ROS_PACKAGE_NAME,
"Expanded and remapped topic name '%s'", remapped_topic_name);
106 RCL_CHECK_FOR_NULL_WITH_MSG(
112 publisher->
impl->rmw_handle = rmw_create_publisher(
118 RCL_CHECK_FOR_NULL_WITH_MSG(
119 publisher->
impl->rmw_handle, rmw_get_error_string().str,
goto fail);
121 rmw_ret_t rmw_ret = rmw_publisher_get_actual_qos(
122 publisher->
impl->rmw_handle,
123 &publisher->
impl->actual_qos);
124 if (RMW_RET_OK != rmw_ret) {
125 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
128 publisher->
impl->actual_qos.avoid_ros_namespace_conventions =
129 options->
qos.avoid_ros_namespace_conventions;
131 publisher->
impl->options = *options;
133 if (
RCL_RET_OK != rcl_node_type_cache_register_type(
134 node, type_support->get_type_hash_func(type_support),
135 type_support->get_type_description_func(type_support),
136 type_support->get_type_description_sources_func(type_support)))
138 rcutils_reset_error();
139 RCL_SET_ERROR_MSG(
"Failed to register type for subscription");
142 publisher->
impl->type_hash = *type_support->get_type_hash_func(type_support);
144 RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME,
"Publisher initialized");
147 TRACETOOLS_TRACEPOINT(
149 (
const void *)publisher,
151 (
const void *)publisher->
impl->rmw_handle,
157 if (publisher->
impl) {
158 if (publisher->
impl->rmw_handle) {
159 rmw_ret_t rmw_fail_ret = rmw_destroy_publisher(
161 if (RMW_RET_OK != rmw_fail_ret) {
162 RCUTILS_SAFE_FWRITE_TO_STDERR(rmw_get_error_string().str);
163 RCUTILS_SAFE_FWRITE_TO_STDERR(
"\n");
167 allocator->deallocate(publisher->
impl, allocator->state);
168 publisher->
impl = NULL;
174 allocator->deallocate(remapped_topic_name, allocator->state);
192 RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME,
"Finalizing publisher");
193 if (publisher->
impl) {
200 rmw_destroy_publisher(rmw_node, publisher->
impl->rmw_handle);
201 if (ret != RMW_RET_OK) {
202 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
206 ROSIDL_TYPE_HASH_VERSION_UNSET != publisher->
impl->type_hash.version &&
207 RCL_RET_OK != rcl_node_type_cache_unregister_type(node, &publisher->
impl->type_hash))
209 RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
212 allocator.deallocate(publisher->
impl, allocator.state);
213 publisher->
impl = NULL;
215 RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME,
"Publisher finalized");
225 default_options.
qos = rmw_qos_profile_default;
230 bool disable_loaned_message =
false;
235 RCUTILS_SAFE_FWRITE_TO_STDERR(
"Failed to get disable_loaned_message: ");
236 RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
241 return default_options;
247 const rosidl_message_type_support_t * type_support,
253 return rcl_convert_rmw_ret_to_rcl_ret(
254 rmw_borrow_loaned_message(publisher->
impl->rmw_handle, type_support, ros_message));
260 void * loaned_message)
266 return rcl_convert_rmw_ret_to_rcl_ret(
267 rmw_return_loaned_message_from_publisher(publisher->
impl->rmw_handle, loaned_message));
273 const void * ros_message,
274 rmw_publisher_allocation_t * allocation)
283 TRACETOOLS_TRACEPOINT(
rcl_publish, (
const void *)publisher, (
const void *)ros_message);
284 if (rmw_publish(publisher->
impl->rmw_handle, ros_message, allocation) != RMW_RET_OK) {
285 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
295 rmw_publisher_allocation_t * allocation)
301 TRACETOOLS_TRACEPOINT(
rcl_publish, (
const void *)publisher, (
const void *)serialized_message);
302 rmw_ret_t ret = rmw_publish_serialized_message(
303 publisher->
impl->rmw_handle, serialized_message, allocation);
304 if (ret != RMW_RET_OK) {
305 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
306 if (ret == RMW_RET_BAD_ALLOC) {
318 rmw_publisher_allocation_t * allocation)
324 TRACETOOLS_TRACEPOINT(
rcl_publish, (
const void *)publisher, (
const void *)ros_message);
325 rmw_ret_t ret = rmw_publish_loaned_message(publisher->
impl->rmw_handle, ros_message, allocation);
326 if (ret != RMW_RET_OK) {
327 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
339 if (rmw_publisher_assert_liveliness(publisher->
impl->rmw_handle) != RMW_RET_OK) {
340 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
353 rmw_time_t rmw_timeout;
356 rmw_timeout.nsec = timeout % 1000000000;
357 }
else if (timeout < 0) {
358 rmw_time_t infinite = RMW_DURATION_INFINITE;
359 rmw_timeout = infinite;
361 rmw_time_t zero = RMW_DURATION_UNSPECIFIED;
365 rmw_ret_t ret = rmw_publisher_wait_for_all_acked(publisher->
impl->rmw_handle, rmw_timeout);
366 if (ret != RMW_RET_OK) {
367 if (ret == RMW_RET_TIMEOUT) {
370 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
371 if (ret == RMW_RET_UNSUPPORTED) {
387 return publisher->
impl->rmw_handle->topic_name;
396 return &publisher->
impl->options;
405 return publisher->
impl->rmw_handle;
414 return publisher->
impl->context;
424 if (!rcl_error_is_set()) {
427 RCL_SET_ERROR_MSG(
"publisher's context is invalid");
431 RCL_CHECK_FOR_NULL_WITH_MSG(
432 publisher->
impl->rmw_handle,
"publisher's rmw handle is invalid",
return false);
439 RCL_CHECK_FOR_NULL_WITH_MSG(publisher,
"publisher pointer is invalid",
return false);
440 RCL_CHECK_FOR_NULL_WITH_MSG(
441 publisher->
impl,
"publisher implementation is invalid",
return false);
442 RCL_CHECK_FOR_NULL_WITH_MSG(
443 publisher->
impl->rmw_handle,
"publisher's rmw handle is invalid",
return false);
450 size_t * subscription_count)
457 rmw_ret_t ret = rmw_publisher_count_matched_subscriptions(
458 publisher->
impl->rmw_handle, subscription_count);
460 if (ret != RMW_RET_OK) {
461 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
462 return rcl_convert_rmw_ret_to_rcl_ret(ret);
467 const rmw_qos_profile_t *
473 return &publisher->
impl->actual_qos;
487 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.