While Agnocast can be applied incrementally on a per-topic basis to nodes that inherit from rclcpp::Node, we also provide agnocast::Node for users who seek further performance improvements.
agnocast::Node offers an API that is largely compatible with rclcpp::Node, allowing existing nodes to be migrated by simply replacing rclcpp::Node with agnocast::Node.
However, some APIs are not yet supported, and others are intentionally not planned to be supported.
This document summarizes those limitations.
Since rclcpp::Node is composed of ten modular node interfaces, this document organizes the API compatibility of agnocast::Node accordingly, one section per interface.
Key Characteristics of agnocast::Node:
agnocast::Nodeis a node implementation that bypasses the RMW layer entirely (e.g., it does not create a DDS participant)- When run as a standalone node (i.e., not loaded into a Component Container), nodes inheriting from
agnocast::Nodemust be executed with Agnocast-only executors (i.e.,AgnocastOnlySingleThreadedExecutor,AgnocastOnlyMultiThreadedExecutororAgnocastOnlyCallbackIsolatedExecutor). In contrast, when such nodes are loaded into a Component Container, the container’s Agnocast-compatible executors—SingleThreadedAgnocastExecutor,MultiThreadedAgnocastExecutor, andCallbackIsolatedAgnocastExecutor—can also be used.
rclcpp::Node consists of 10 interface components:
- NodeBaseInterface - Core node identity and callback management
- NodeTopicsInterface - Publisher/Subscription management
- NodeParametersInterface - Parameter management
- NodeGraphInterface - ROS graph introspection
- NodeServicesInterface - Service client/server management
- NodeTimersInterface - Timer management
- NodeLoggingInterface - Logging functionality
- NodeClockInterface - Time and clock management
- NodeWaitablesInterface - Custom waitable management
- NodeTimeSourceInterface - Time source configuration
Each interface is accessible via getter methods such as get_node_base_interface(), get_node_topics_interface(), etc.
Purpose: Core node identity, context management, callback groups
Important: agnocast::node_interfaces::NodeBase inherits from rclcpp::node_interfaces::NodeBaseInterface.
| Feature | agnocast::Node | Support Level | Planned | Notes |
|---|---|---|---|---|
get_name() |
✓ | Full Support | - | |
get_namespace() |
✓ | Full Support | - | |
get_fully_qualified_name() |
✓ | Full Support | - | |
get_context() |
✓ | Full Support | - | Returns rclcpp::Context::SharedPtr passed when using Component Container. Returns nullptr if not loaded in Component Container |
get_rcl_node_handle() |
✗ | Throws Exception | No | Throws std::runtime_error because DDS is not used |
get_shared_rcl_node_handle() |
✗ | Throws Exception | No | Throws std::runtime_error because DDS is not used |
create_callback_group() |
✓ | Full Support | - | |
get_default_callback_group() |
✓ | Full Support | - | |
callback_group_in_node() |
✓ | Full Support | - | |
for_each_callback_group() |
✓ | Full Support | - | |
get_notify_guard_condition() |
✗ | Throws Exception | Yes | Not needed as agnocast uses epoll instead of condition variables, but planned for loading into Component Container |
get_associated_with_executor_atomic() |
✓ | Full Support | - | |
resolve_topic_or_service_name() |
✓ | Full Support | - | Used by NodeTopics and (future) NodeServices |
get_use_intra_process_default() |
⚠ | API Only | No | Returns value while logging a warning. agnocast uses its own shared memory IPC, so rclcpp's intra_process_communication is not used. |
get_enable_topic_statistics_default() |
⚠ | API Only | Yes | Returns value passed from NodeOptions. |
Purpose: Publisher and Subscription management
| Feature | agnocast::Node | Support Level | Planned | Notes |
|---|---|---|---|---|
resolve_topic_name() |
✓ | Full Support | - | |
get_node_base_interface() |
✓ | Full Support | - | |
create_publisher() |
✗ | Throws Exception | No | Use agnocast::create_publisher() or agnocast::Node::create_publisher() |
add_publisher() |
✗ | Throws Exception | No | Uses agnocast's own Publisher management |
create_subscription() |
✗ | Throws Exception | No | Use agnocast::create_subscription() or agnocast::Node::create_subscription() |
add_subscription() |
✗ | Throws Exception | No | Uses agnocast's own Subscription management |
get_node_timers_interface() |
✗ | Throws Exception | TBD | Use agnocast::Node::create_wall_timer() or agnocast::Node::create_timer() instead |
Purpose: Parameter declaration, access, and management
Important: agnocast::node_interfaces::NodeParameters inherits from rclcpp::node_interfaces::NodeParametersInterface.
| Feature | agnocast::Node | Support Level | Planned | Notes |
|---|---|---|---|---|
declare_parameter(name, default_value) |
✓ | Full Support | - | |
declare_parameter(name, type) |
✓ | Full Support | - | |
undeclare_parameter() |
✓ | Full Support | - | |
has_parameter() |
✓ | Full Support | - | |
get_parameter(name) |
✓ | Full Support | - | |
get_parameter(name, param&) |
✓ | Full Support | - | |
get_parameters(names) |
✓ | Full Support | - | |
get_parameter_overrides() |
✓ | Full Support | - | |
set_parameters() |
✓ | Full Support | - | Parameter events not triggered (see below) |
set_parameters_atomically() |
✓ | Full Support | - | Parameter events not triggered (see below) |
get_parameters_by_prefix() |
✓ | Full Support | - | |
describe_parameters() |
✓ | Full Support | - | |
get_parameter_types() |
✓ | Full Support | - | |
list_parameters() |
✓ | Full Support | - | |
add_on_set_parameters_callback() |
✓ | Full Support | - | |
remove_on_set_parameters_callback() |
✓ | Full Support | - | |
| Parameter Service | ✓ | Full Support | - | |
| Parameter Client | ✓ | Partial Support | - | AsyncParametersClient is supported while SyncParametersClient is not yet |
Other differences from rclcpp::NodeParameters:
| Item | rclcpp::NodeParameters | agnocast::NodeParameters | Planned |
|---|---|---|---|
| Parameter Event Publishing | Publishes to /parameter_events |
None | TBD |
Purpose: Clock access
| Feature | agnocast::Node | Support Level | Planned | Notes |
|---|---|---|---|---|
get_clock() |
✓ | Full Support | - |
Purpose: Time source configuration for simulated time (use_sim_time)
| Feature | agnocast::Node | Support Level | Planned | Notes |
|---|---|---|---|---|
use_sim_time parameter |
✓ | Full Support | - | Declared at node construction |
/clock subscription |
✓ | Full Support | - | Subscribes when use_sim_time:=true |
| ROS time override | ✓ | Full Support | - | Uses rcl_*_ros_time_override() functions |
Unimplemented Features (compared to rclcpp::TimeSource):
| Feature | Impact | Notes |
|---|---|---|
| Multiple clocks | Low | agnocast::Node uses single clock; rarely needed |
| Message caching | Low | Only matters when attaching clocks after /clock messages arrive |
| Dynamic parameter change | Low | Typically use_sim_time is set at launch time and not changed at runtime (e.g., Autoware's logging_simulation). Note: dynamic deactivation of ROS time (use_sim_time changed from true to false) is not yet supported for create_timer() timers. |
Purpose: Service and Client management
| Feature | agnocast::Node | Support Level | Planned | Notes |
|---|---|---|---|---|
add_client() |
✗ | Throws Exception | No | Use agnocast::create_client() or agnocast::Node::create_client() |
add_service() |
✗ | Throws Exception | No | Use agnocast::create_service() or agnocast::Node::create_service() |
resolve_service_name() |
✓ | Full Support | - |
Purpose: Logging functionality
Important: agnocast::node_interfaces::NodeLogging inherits from rclcpp::node_interfaces::NodeLoggingInterface.
| Feature | agnocast::Node | Support Level | Planned | Notes |
|---|---|---|---|---|
get_logger() |
✓ | Full Support | - | |
get_logger_name() |
✓ | Full Support | - |
Purpose: Graph
Important: agnocast::node_interfaces::NodeGraph inherits from rclcpp::node_interfaces::NodeGraphInterface.
| Feature | agnocast::Node | Support Level | Planned | Notes |
|---|---|---|---|---|
get_topic_names_and_types() |
✗ | Throws Exception | No | To support this, topic_name and topic_type must be managed within the kmod; however, they are currently not managed |
get_service_names_and_types() |
✗ | Throws Exception | No | Agnocast does not officially support Service |
get_service_names_and_types_by_node() |
✗ | Throws Exception | No | Agnocast does not officially support Service |
get_client_names_and_types_by_node() |
✗ | Throws Exception | No | Agnocast does not officially support Service |
get_publisher_names_and_types_by_node() |
✗ | Throws Exception | No | To support this, topic_name and topic_type must be managed within the kmod; however, they are currently not managed |
get_subscriber_names_and_types_by_node() |
✗ | Throws Exception | No | To support this, topic_name and topic_type must be managed within the kmod; however, they are currently not managed |
get_node_names() |
✗ | Throws Exception | Yes | To support this, the kmod must report the nodes owning an agnocast endpoint; it currently does not |
get_node_names_with_enclaves() |
✗ | Throws Exception | No | |
get_node_names_and_namespaces() |
✗ | Throws Exception | No | To support this, namespace must be managed within the kmod; however, they are currently not managed |
count_publishers() |
✓ | Full Support | - | Counts agnocast and ROS 2 publishers, excluding those created by bridges. agnocast::Node::count_publishers() delegates here |
count_subscribers() |
✓ | Partial Support | - | Counts agnocast and ROS 2 subscribers, excluding those created by bridges. Agnocast subscribers in the caller's own process are not counted. agnocast::Node::count_subscribers() delegates here |
get_graph_guard_condition() |
✗ | Throws Exception | No | |
notify_graph_change() |
- | No-op | No | agnocast has no graph events, so there is nothing to notify. Made a no-op because rclcpp utilities call it unconditionally |
notify_shutdown() |
- | No-op | No | Same as notify_graph_change() |
get_graph_event() |
✗ | Throws Exception | No | |
wait_for_graph_change() |
✗ | Throws Exception | No | |
count_graph_users() |
✗ | Throws Exception | No | |
get_publishers_info_by_topic() |
✗ | Throws Exception | No | To support this, namespace and topic_type must be managed within the kmod; however, they are currently not managed |
get_subscriptions_info_by_topic() |
✗ | Throws Exception | No | To support this, namespace and topic_type must be managed within the kmod; however, they are currently not managed |
The following interfaces are all unsupported. agnocast::Node does not implement these interfaces.
| Interface | Support Status | Planned | Notes |
|---|---|---|---|
| NodeTimersInterface | Unsupported | Yes | |
| NodeWaitablesInterface | Unsupported | TBD |
agnocast uses rcl_parse_arguments() to parse command line arguments.
This provides the same argument parsing functionality as rcl.
| Argument Type | agnocast | Support Level | Planned | Notes |
|---|---|---|---|---|
--ros-args |
✓ | Full Support | - | ROS arguments start marker |
-r topic:=new_topic |
✓ | Full Support | - | Topic name remapping |
-r __ns:=/namespace |
✓ | Full Support | - | Change node namespace |
-r __node:=name |
✓ | Full Support | - | Change node name |
-p param:=value |
✓ | Full Support | - | Set parameter value |
--params-file file.yaml |
✓ | Full Support | - | Load parameters from YAML file |
-- (end marker) |
✓ | Full Support | - | ROS arguments end marker |
-r node:old:=new |
✓ | Full Support | - | Node-specific remapping |
--log-level |
✓ | Full Support | - | Set log level |
--enable-rosout-logs |
✗ | Unsupported | TBD | Enable logging to rosout |
--disable-external-lib-logs |
✓ | Full Support | - | Disable external library logs (file logging via rcl_logging_spdlog) |
--disable-stdout-logs |
✓ | Full Support | - | Disable stdout logging |
-e (enclave) |
✗ | Unsupported | TBD | Specify security enclave |
agnocast resolves parameter overrides with resolve_parameter_overrides().
This provides equivalent functionality to rclcpp's rclcpp::detail::resolve_parameter_overrides().
Priority Order (highest priority first):
parameter_overrides(from NodeOptions::parameter_overrides())local_args(from NodeOptions::arguments())global_args(from command line)
| Feature | agnocast | Support Level | Planned |
|---|---|---|---|
Private topic (~topic) |
✓ | Full Support | - |
Relative topic (topic) |
✓ | Full Support | - |
Absolute topic (/topic) |
✓ | Full Support | - |
Substitution ({node}) |
✓ | Full Support | - |
Substitution ({ns}, {namespace}) |
✓ | Full Support | - |
| Topic remapping | ✓ | Full Support | - |
| Service remapping | ⚠ | Unused | Yes |
agnocast::Node provides the following two constructors, same as rclcpp::Node:
// Constructor 1: Node name only (NodeOptions optional)
explicit Node(
const std::string & node_name,
const rclcpp::NodeOptions & options = rclcpp::NodeOptions());
// Constructor 2: Node name + namespace (NodeOptions optional)
explicit Node(
const std::string & node_name,
const std::string & namespace_,
const rclcpp::NodeOptions & options = rclcpp::NodeOptions());The following tables compare methods that are directly defined in each class. "Directly defined" means methods defined in the class itself, not those accessible only via interfaces.
| API | rclcpp::Node | agnocast::Node | Notes |
|---|---|---|---|
get_name() |
✓ | ✓ | |
get_namespace() |
✓ | ✓ | |
get_fully_qualified_name() |
✓ | ✓ | |
get_logger() |
✓ | ✓ |
| API | rclcpp::Node | agnocast::Node | Notes |
|---|---|---|---|
create_callback_group() |
✓ | ✓ | |
for_each_callback_group() |
✓ | ✓ |
| API | rclcpp::Node | agnocast::Node | Notes |
|---|---|---|---|
create_publisher<MessageT>() |
✓ | ✓ | Return type differs (rclcpp::Publisher vs agnocast::Publisher) |
create_subscription<MessageT>() |
✓ | ✓ | Return type differs (rclcpp::Subscription vs agnocast::Subscription) |
create_generic_publisher() |
✓ | ✗ | |
create_generic_subscription() |
✓ | ✗ |
| API | rclcpp::Node | agnocast::Node | Notes |
|---|---|---|---|
declare_parameter() |
✓ | ✓ | |
declare_parameters() |
✓ | ✗ | |
undeclare_parameter() |
✓ | ✓ | |
has_parameter() |
✓ | ✓ | |
get_parameter() |
✓ | ✓ | |
get_parameter_or() |
✓ | ✗ | |
get_parameters() |
✓ | ✓ | |
set_parameter() |
✓ | ✓ | |
set_parameters() |
✓ | ✓ | |
set_parameters_atomically() |
✓ | ✓ | |
describe_parameter() |
✓ | ✓ | |
describe_parameters() |
✓ | ✓ | |
get_parameter_types() |
✓ | ✓ | |
list_parameters() |
✓ | ✓ | |
add_on_set_parameters_callback() |
✓ | ✓ | |
remove_on_set_parameters_callback() |
✓ | ✓ |
| API | rclcpp::Node | agnocast::Node | Notes |
|---|---|---|---|
create_wall_timer() |
✓ | ✓ | Return type differs (uint32_t timer_id vs rclcpp::TimerBase::SharedPtr) |
create_timer() |
✓ | ✓ | Supports ROS_TIME (simulation time). Return type differs (agnocast::TimerBase::SharedPtr vs rclcpp::TimerBase::SharedPtr). Note: dynamic deactivation of ROS time (use_sim_time changed from true to false at runtime) is not yet supported. |
create_client<ServiceT>() |
✓ | ✓ | Return type differs (rclcpp::Client vs. agnocast::Client). |
create_service<ServiceT>() |
✓ | ✓ | Return type differs (rclcpp::Service vs. agnocast::Service). |
| API | rclcpp::Node | agnocast::Node |
|---|---|---|
get_node_names() |
✓ | ✗ |
get_topic_names_and_types() |
✓ | ✗ |
get_service_names_and_types() |
✓ | ✗ |
get_service_names_and_types_by_node() |
✓ | ✗ |
count_publishers() |
✓ | ✓ |
count_subscribers() |
✓ | ✓ |
get_publishers_info_by_topic() |
✓ | ✗ |
get_subscriptions_info_by_topic() |
✓ | ✗ |
get_graph_event() |
✓ | ✗ |
wait_for_graph_change() |
✓ | ✗ |
| API | rclcpp::Node | agnocast::Node | Notes |
|---|---|---|---|
get_clock() |
✓ | ✓ | |
now() |
✓ | ✓ |
| API | rclcpp::Node | agnocast::Node | Notes |
|---|---|---|---|
get_node_base_interface() |
✓ | ✓ | |
get_node_topics_interface() |
✓ | ✓ | |
get_node_parameters_interface() |
✓ | ✓ | |
get_node_clock_interface() |
✓ | ✓ | |
get_node_graph_interface() |
✓ | ✗ | |
get_node_logging_interface() |
✓ | ✓ | |
get_node_timers_interface() |
✓ | ✗ | |
get_node_services_interface() |
✓ | ✓ | |
get_node_waitables_interface() |
✓ | ✗ | |
get_node_time_source_interface() |
✓ | ✓ |
| API | rclcpp::Node | agnocast::Node | Notes |
|---|---|---|---|
get_sub_namespace() |
✓ | ✗ | Sub-nodes not supported |
get_effective_namespace() |
✓ | ✗ | Sub-nodes not supported |
create_sub_node() |
✓ | ✗ | Sub-nodes not supported |
| API | rclcpp::Node | agnocast::Node | Notes |
|---|---|---|---|
get_node_options() |
✓ | ✗ |
| Aspect | agnocast | Notes |
|---|---|---|
| Global context required | ✗ (Optional) | Works without agnocast::init() |
| NodeOptions support | ✓ | Supports parameter_overrides, context, arguments, etc. |
| Sub-nodes | ✗ | agnocast does not support sub-nodes |
| Lifecycle nodes | ✗ | Not applicable |
agnocast::Node implements rclcpp::node_interfaces::NodeBaseInterface, so it can be loaded as a Composable Node into a Component Container.
Note: While agnocast::Node can be loaded into a Component Container, the Component Container itself becomes a DDS participant. Therefore, the performance maximization benefits—which are the primary purpose of using agnocast::Node—cannot be fully realized when using a Component Container.
agnocast::Node uses the following rcl/rclcpp functions, data structures, and classes:
rcl Functions:
rcl_parse_arguments()- Command line argument parsingrcl_arguments_copy()- Argument copyingrcl_expand_topic_name()- Topic name expansionrcl_remap_topic_name()- Topic remappingrcl_remap_node_name()- Node name remappingrcl_remap_node_namespace()- Namespace remappingrcl_arguments_get_param_overrides()- Get parameter overridesrcl_arguments_fini()- Argument cleanuprcl_get_default_allocator()- Get default allocatorrcl_logging_configure_with_output_handler()- Configure rcl logging with file output via rcl_logging_spdlogrcl_logging_multiple_output_handler()- Default output handler that dispatches to stdout and external lib (spdlog)rcl_enable_ros_time_override()- Enable ROS time override for simulated timercl_disable_ros_time_override()- Disable ROS time overridercl_set_ros_time_override()- Set ROS time override value
rcl Data Structures:
rcl_arguments_t- Parsed arguments
rclcpp Functions:
rclcpp::detail::declare_qos_parameters()- Declares QoS-related parameters and applies overrides. This function only requiresNodeParametersInterfaceand internally callsdeclare_parameter/get_parameter, so it works withagnocast::Node. WhenQosOverridingOptionsis specified, QoS policies are automatically applied from parameters using the naming conventionqos_overrides.<topic>.<entity>.<policy>(e.g.,qos_overrides./my_topic.subscription.durability), without requiring explicit parameter declaration in user code.rclcpp::exceptions::throw_from_rcl_error()- Throw exception from rcl error
rclcpp Classes/Interfaces:
rclcpp::Context- Context managementrclcpp::CallbackGroup- Callback group managementrclcpp::Logger- Loggingrclcpp::Parameter/rclcpp::ParameterValue- Parameter managementrclcpp::QoS- QoS configurationrclcpp::QosOverridingOptions- QoS override configuration via parametersrclcpp::NodeOptions- Node construction optionsrclcpp::node_interfaces::NodeBaseInterface- Node base interface (inherited)rclcpp::node_interfaces::NodeTopicsInterface- Node topics interface (inherited)rclcpp::node_interfaces::NodeParametersInterface- Node parameters interface (inherited)rclcpp::node_interfaces::ParameterMutationRecursionGuard- RAII guard to prevent recursive parameter modifications from within callbacksrclcpp::node_interfaces::ParameterInfo- Parameter value and descriptor storagerclcpp::node_interfaces::OnSetParametersCallbackHandle- Handle for parameter set callbacksrclcpp::node_interfaces::NodeClockInterface- Node clock interface (inherited)rclcpp::node_interfaces::NodeTimeSourceInterface- Node time source interface (inherited)rclcpp::node_interfaces::NodeLoggingInterface- Node logging interface (inherited)rclcpp::Clock- Clock managementrclcpp::Clock::create_jump_callback()- Register time jump callbacks (used bycreate_timer()for ROS_TIME support)rclcpp::JumpHandler- RAII handle for time jump callbacksrclcpp::Time- Time representation
Message Types:
rosgraph_msgs::msg::Clock- Clock message for simulated time