|
28 | 28 | # 1. Boot: broken_lidar_3_0_0 is applied (entrypoint auto-apply) and |
29 | 29 | # scan_sensor_node is running broken_lidar_node; fixed_lidar_3_0_1 is |
30 | 30 | # NOT yet registered (boot catalog holds only the bad update). |
31 | | -# 2. send-goal.sh -> ACTION_NAVIGATE_TO_POSE_ABORTED reaches CONFIRMED on |
32 | | -# bt-navigator, and controller-server picks up a supporting LOG_* fault |
33 | | -# whose message is the controller's own stall, not just any error. |
| 31 | +# 2. Once action_status_bridge is watching /navigate_to_pose (the goal must |
| 32 | +# not precede it - see wait_for_action_bridge), send-goal.sh -> |
| 33 | +# ACTION_NAVIGATE_TO_POSE_ABORTED reaches CONFIRMED on bt-navigator, and |
| 34 | +# controller-server picks up a supporting LOG_* fault whose message is |
| 35 | +# the controller's own stall, not just any error. |
34 | 36 | # 3. Fault detail (bt-navigator) has environment_data.snapshots >= 1, and |
35 | 37 | # the rosbag bulk-data download returns a non-empty MCAP body. |
36 | 38 | # 4. publish-fix.sh -> fixed_lidar_3_0_1 appears in /updates (SOVD |
@@ -170,6 +172,31 @@ poll_process_running() { |
170 | 172 | return 1 |
171 | 173 | } |
172 | 174 |
|
| 175 | +# Wait until action_status_bridge says it is watching navigate_to_pose. |
| 176 | +# |
| 177 | +# The goal must not be sent before this. The bridge fixes a fault's source on |
| 178 | +# the FIRST status message it sees for an action, and the action status topic |
| 179 | +# is transient-local: a bridge that subscribes while a goal is already in |
| 180 | +# flight gets a latched sample immediately, before the ROS graph has resolved |
| 181 | +# the publisher's node name. The source then stays the action name |
| 182 | +# (/navigate_to_pose) instead of the server's node (/bt_navigator), and the |
| 183 | +# fault never lands on the bt-navigator entity this test asserts on. |
| 184 | +# |
| 185 | +# demo.launch.py starts the bridges on a 15 s timer while send-goal.sh retries |
| 186 | +# until nav2 accepts, so on a fast boot the goal wins that race. |
| 187 | +wait_for_action_bridge() { |
| 188 | + local timeout="${1:-60}" |
| 189 | + local elapsed=0 |
| 190 | + while [ $elapsed -lt "$timeout" ]; do |
| 191 | + if docker logs "$GATEWAY_CONTAINER" 2>&1 | grep -q "Watching action '/navigate_to_pose'"; then |
| 192 | + return 0 |
| 193 | + fi |
| 194 | + sleep 2 |
| 195 | + elapsed=$((elapsed + 2)) |
| 196 | + done |
| 197 | + return 1 |
| 198 | +} |
| 199 | + |
173 | 200 | # Poll until `pgrep -af <pattern>` fails inside the gateway container |
174 | 201 | # (process gone), up to $2 seconds. |
175 | 202 | poll_process_gone() { |
|
232 | 259 | # --------------------------------------------------------------------- |
233 | 260 | section "Reactive fault: send-goal.sh triggers ACTION_NAVIGATE_TO_POSE_ABORTED" |
234 | 261 |
|
| 262 | +echo " Waiting for action_status_bridge to watch /navigate_to_pose (max 60s)..." |
| 263 | +if wait_for_action_bridge 60; then |
| 264 | + pass "action_status_bridge is watching /navigate_to_pose before the goal is sent" |
| 265 | +else |
| 266 | + fail "action_status_bridge is watching /navigate_to_pose before the goal is sent" \ |
| 267 | + "bridge never reported the action within 60s - a goal sent now would be attributed to the action name, not to bt-navigator" |
| 268 | + exit 1 |
| 269 | +fi |
| 270 | + |
235 | 271 | # x=1.8, y=2.3 (frame map) drives straight into the phantom sector so nav2 |
236 | 272 | # reliably stalls - the send-goal.sh script defaults elsewhere are for |
237 | 273 | # ad-hoc operator use, not this repeatable regression check. |
|
0 commit comments