feat: add LifecycleNode support to ManagedNitrosPublisher/Subscriber (fix #68) - #70
feat: add LifecycleNode support to ManagedNitrosPublisher/Subscriber (fix #68)#70eclipse0922 wants to merge 5 commits into
Conversation
|
Hi @eclipse0922 and @yuanknv , I’m looking to use LifecycleNode support for ManagedNitrosPublisher/Subscriber in my own project and this PR perfectly addresses the limitation in #68. I was wondering if there are any plans to merge this PR in the near future? I would really appreciate it if possible, thank you! |
…ix NVIDIA-ISAAC-ROS#68) Introduces `NitrosNodeInterfaces` — a `rclcpp::node_interfaces::NodeInterfaces` type alias — so that the entire NitrosPublisher/Subscriber stack accepts any node-like type (rclcpp::Node, rclcpp_lifecycle::LifecycleNode, or custom) without modification to downstream code. Key changes: - New `nitros_node_interfaces.hpp`: `NitrosNodeInterfaces` type alias + `MakeNitrosNodeInterfaces<NodeT>()` factory - `NitrosPublisherSubscriberBase`, `NitrosPublisher`, `NitrosSubscriber`: primary constructors accept `NitrosNodeInterfaces`; existing `rclcpp::Node &` constructors remain as backward-compatible delegating wrappers (no API break) - `NitrosFormatAgent` callbacks: use `rclcpp::create_publisher/subscription` free functions with `NitrosNodeInterfaces` instead of node member functions - `NitrosTypeManager`: adds `rclcpp::Logger`-based constructor, removing the mandatory `rclcpp::Node *` dependency - `ManagedNitrosPublisher/Subscriber`: template `<typename NodeT>` constructors accept any node pointer; `rclcpp::Node *` path continues to work unchanged - New lifecycle test: `NitrosEmptyLifecycleNode` composable component in `isaac_ros_managed_nitros/test/` demonstrates and validates LifecycleNode integration (requires GPU for full runtime test, mirrors existing tests) All linter checks (cpplint, flake8, uncrustify, pep257, lint_cmake, xmllint) pass. Runtime integration tests require GPU access, consistent with existing upstream tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix null callback crash: guard lambda in ManagedNitrosSubscriber before calling callback(view) when callback == nullptr (was silent UB) - Add ManagedNitrosSubscriber<NitrosEmptyView> to lifecycle test node, exercising subscriber construction + cleanup in LifecycleNode context - Add test_lifecycle_configure_and_cleanup test method (configure → cleanup cycle verifies resource teardown path) - Refactor launch test to canonical IsaacROSBaseTest.generate_test_description pattern; remove duplicate create_client call; fix import order (flake8) - Update copyright years to 2022-2025 in all 7 modified files - Add NitrosEmptyView definition (via view factory macro) in test source to satisfy ManagedNitrosSubscriber<NitrosMsgView>::BaseType requirement Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Separating configure and cleanup into two test methods caused cross-test state leakage: the first method left the node in 'inactive', making the second method's configure call invalid (configure is only legal from 'unconfigured' in ROS 2 lifecycle semantics). Consolidate into one test_lifecycle_configure_and_cleanup that drives configure → cleanup → configure to verify both construction and teardown/re-creation of ManagedNitrosPublisher/Subscriber in a single deterministic sequence. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers all five on_*() callbacks in one ordered test: configure → activate → deactivate → cleanup → configure → shutdown Previously only configure and cleanup were exercised. on_activate, on_deactivate, and on_shutdown had zero coverage. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
e8f685f to
a60cda9
Compare
|
Rebased this branch onto the latest Changes made during the rebase:
Verification (against 4.5.0 binary packages, ROS 2 Jazzy):
|
|
@AshishA26 |
|
I appreciate your fast response @eclipse0922. Thank you letting me know and making it up-to-date as well! |
Summary
Fixes #68 —
ManagedNitrosPublisherandManagedNitrosSubscriberpreviously required a rawrclcpp::Node*, which prevented them from being used insiderclcpp_lifecycle::LifecycleNode. This PR makes both classes work with any node type that exposes the standard ROS 2 node interfaces.Approach
The core change is replacing the
rclcpp::Node*constructor parameter withrclcpp::node_interfaces::NodeInterfaces<...>, which is a node-agnostic interface bundle accepted by bothrclcpp::Nodeandrclcpp_lifecycle::LifecycleNode(and any custom node type).A new
NitrosNodeInterfacestype alias andMakeNitrosNodeInterfaces<NodeT>(node)template factory are introduced innitros_node_interfaces.hpp. This keeps all interface extraction logic in one place and avoids duplicating the long template parameter list across files.ManagedNitrosPublisherandManagedNitrosSubscribernow accept anyNodeT*through a templated constructor and immediately capture the interfaces:This is fully backwards-compatible: existing code passing
rclcpp::Node*continues to work without changes.Changes
New file
isaac_ros_nitros/include/isaac_ros_nitros/nitros_node_interfaces.hpp—NitrosNodeInterfacestype alias andMakeNitrosNodeInterfaces<NodeT>factoryModified: core NITROS
nitros_publisher_subscriber_base.hppNitrosNodeInterfacesinstead ofrclcpp::Node*; store by value; add#include <utility>nitros_publisher.hpp/.cppNitrosNodeInterfacesthrough constructor chainnitros_subscriber.hpp/.cppNitrosNodeInterfaces; usenode_ifaces_.get<NodeClockInterface>()->get_clock()for timerModified: managed wrappers
managed_nitros_publisher.hppNodeT*constructor →MakeNitrosNodeInterfaces; storeNitrosNodeInterfacesmanaged_nitros_subscriber.hppif (callback)null-guard before invoking user callbackNew test
test/src/nitros_empty_lifecycle_node.cpprclcpp_lifecycle::LifecycleNodecomponent that creates aManagedNitrosPublisher<NitrosEmpty>andManagedNitrosSubscriber<NitrosEmptyView>inon_configure()and destroys them inon_cleanup()/on_shutdown()test/isaac_ros_nitros_lifecycle_test_pol.pyon_cleanup(), (3) successful re-construction after cleanupTest Results
Tested inside the
vision-platform:visionDocker image with GPU passthrough (--gpus all --ipc=host):All linter checks pass:
cpplint,uncrustify,flake8,pep257,xmllint.Backwards Compatibility
No breaking changes. Existing code that creates
ManagedNitrosPublisherorManagedNitrosSubscriberwith anrclcpp::Node*continues to compile and run without modification. The internalNitrosPublisher/NitrosSubscriberAPIs are not public, so their constructor signature change is not a user-facing break.