|
2 | 2 |
|
3 | 3 | import unittest |
4 | 4 |
|
5 | | -from helpers import TIMEOUT, wait_for_node_state, wait_for_topic_message |
| 5 | +from helpers import TIMEOUT, wait_for_node_state |
6 | 6 | import launch |
7 | 7 | import launch_ros.actions |
8 | 8 | import launch_testing |
@@ -96,22 +96,29 @@ def _test_sync_node(self, namespace): |
96 | 96 | """Test that a sync node publishes a combined output.""" |
97 | 97 | self._wait_active(f"{namespace}/{namespace}") |
98 | 98 |
|
| 99 | + # Subscribe to `output` BEFORE publishing the inputs. The sync node fires its sync callback and publishes once |
| 100 | + # as soon as both inputs land; under RELIABLE QoS the publisher only buffers for subscribers it already knows |
| 101 | + # about, so a sub created after the burst can miss the message on a fast (or cold-discovery) runner. |
| 102 | + received = [None] |
| 103 | + |
| 104 | + def on_output(msg): |
| 105 | + if received[0] is None and "synced:" in msg.data: |
| 106 | + received[0] = msg |
| 107 | + |
| 108 | + sub = self.node.create_subscription(String, f"{namespace}/output", on_output, self.qos) |
| 109 | + |
99 | 110 | pub_a, pub_b = self._publish_synced_points(namespace, 1.0, 2.0, 3.0, 4.0) |
100 | 111 |
|
101 | | - msg = wait_for_topic_message( |
102 | | - self.node, |
103 | | - f"{namespace}/output", |
104 | | - String, |
105 | | - timeout=TIMEOUT, |
106 | | - qos=self.qos, |
107 | | - predicate=lambda m: "synced:" in m.data, |
108 | | - ) |
| 112 | + end = self.node.get_clock().now() + rclpy.duration.Duration(seconds=TIMEOUT) |
| 113 | + while received[0] is None and self.node.get_clock().now() < end: |
| 114 | + rclpy.spin_once(self.node, timeout_sec=0.1) |
109 | 115 |
|
| 116 | + self.node.destroy_subscription(sub) |
110 | 117 | self.node.destroy_publisher(pub_a) |
111 | 118 | self.node.destroy_publisher(pub_b) |
112 | 119 |
|
113 | | - self.assertIsNotNone(msg, f"Did not receive synced output from {namespace}") |
114 | | - self.assertIn("synced:", msg.data) |
| 120 | + self.assertIsNotNone(received[0], f"Did not receive synced output from {namespace}") |
| 121 | + self.assertIn("synced:", received[0].data) |
115 | 122 |
|
116 | 123 | def test_cpp_sync_node(self): |
117 | 124 | """C++ sync node delivers paired messages through sync callback.""" |
|
0 commit comments