ROS 2 pytest publisher "Destroyable" error
Ubuntu 22.04, ROS 2 Humble, (Cyclone DDS to avoid Nav2 issue)
I am working on a unit test for python class which creates a publisher and publishes a message.
I'm running the test via colcon test
from a Python unittest.TestCase
derived class
I am creating an rclpy context, executor, and node as part of the test setUp
, then creating the publisher inside the python code being tested. I verify the node is created properly:
[INFO] [1686855160.909732000] [core_test_7]: set up core test 7 (1)...
[WARN] [1686855160.912112918] [core_test_7]: Node:{<rclpy.node.Node object at 0x7f5da52b56f0>}
[WARN] [1686855160.912704474] [core_test_7]: Context :{<rclpy.context.Context object at 0x7f5da506b9a0>} (1)
But on attempting to publish, I get an exception cannot use Destroyable because ...
:
[WARN] [1686855163.543058631] [core_test_7]: Something went wrong when publishing t!
<class 'rclpy._rclpy_pybind11.InvalidHandle'>: cannot use Destroyable because destruction was requested
[WARN] [1686855163.544163586] [core_test_7]: Publisher:{<rclpy.publisher.Publisher object at 0x7f5da52b4b20>}
[WARN] [1686855163.545204206] [core_test_7]: Node:{<rclpy.node.Node object at 0x7f5da52b56f0>}
[WARN] [1686855163.546243544] [core_test_7]: Context:{<rclpy.context.Context object at 0x7f5da506b9a0>} (1)
The (1) at end is the output of context.ok() method.
There is no explicit call to destroy the node or publisher before calling publish on the publisher instance.
When I tearDown
the node, context, and executor seem OK
INFO] [1686855183.718462381] [core_test_7]: shutting down core test 7 ...
[WARN] [1686855183.719658690] [core_test_7]: Node:{<rclpy.node.Node object at 0x7f5da52b56f0>}
[WARN] [1686855183.720627979] [core_test_7]: Context :{<rclpy.context.Context object at 0x7f5da506b9a0>} (1)
I've tried ensuring shutdown, even killing the ros2 daemon
thinking maybe issue there because the same topic name is used in another test. But nothing has helped.
def setUp(self):
subprocess.run('ros2 daemon stop', shell=True) # Make sure we are starting fresh!
time.sleep(0.1)
TestCore.test += 1
self.context = rclpy.context.Context()
rclpy.init(context=self.context)
self.executor = MultiThreadedExecutor(context=self.context)
self.node = rclpy.create_node("core_test_" + str(self.test), context=self.context)
self.node.get_logger().info(" set up core test %d (%d)... " % (self.test, self.context.ok()))
self.executor.add_node(self.node)
self.node.get_logger().warning(" Node:{%s}" % (str(self.node)))
self.node.get_logger().warning(" Context :{%s} (%d)" % (str(self.context), self.context.ok()))
time.sleep(0.1)
def tearDown(self):
self.node.get_logger().info(" shutting down core test %d ... " % (self.test))
self.node.get_logger().warning(" Node:{%s}" % (str(self.node)))
self.node.get_logger().warning(" Context :{%s} (%d)" % (str(self.context), self.context.ok()))
rclpy.spin_once(self.node, executor=self.executor, timeout_sec=0.1)
self.node.destroy_node()
time.sleep(0.1)
self.executor.shutdown()
time.sleep(0.1)
# Kill it with fire to make sure not stray published topics are available
rclpy.shutdown(context=self.context)
time.sleep(0.2)
subprocess.run('ros2 daemon stop', shell=True) # Make sure we are starting fresh!
time.sleep(0.2)
Any suggestions on fixing or avoiding the Destroyable
error is appreciated.
I also disabled the
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
, and did clean build with default DDS and got the sameDestroyable
execeptionI also tried using the default context and got the same
Destroyable
errorany updates on this? I am getting the same error when running tests.
Unfortunately I don't have a good answer. In the end, I worked around the issue by adding some extra "spin_once" calls in a loop after my test completed to give the system a chance to clean up, before the nodes were destroyed.