ros2 runtime_error ai_generated true

RuntimeError: Cannot cancel goal that is already being cancelled

ID: ros2/nav2-cancel-goal-multiple-times

Also available as: JSON · Markdown · 中文
85%Fix Rate
85%Confidence
1Evidence
2024-02-15First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
ros2-humble active
ros2-iron active
ros2-rolling active

Root Cause

Nav2 action server does not support concurrent cancel requests on the same goal; calling cancel multiple times triggers a race condition in the action server's internal state machine.

generic

中文

Nav2动作服务器不支持对同一目标并发取消请求;多次调用取消会触发动作服务器内部状态机的竞态条件。

Official Documentation

https://docs.nav2.org/behavior_trees/overview.html

Workarounds

  1. 90% success Check if the goal is already in a terminal state before calling cancel: if (goal_handle->get_status() == action_msgs::msg::GoalStatus::STATUS_ACCEPTED || goal_handle->get_status() == action_msgs::msg::GoalStatus::STATUS_EXECUTING) { goal_handle->cancel(); }
    Check if the goal is already in a terminal state before calling cancel: if (goal_handle->get_status() == action_msgs::msg::GoalStatus::STATUS_ACCEPTED || goal_handle->get_status() == action_msgs::msg::GoalStatus::STATUS_EXECUTING) { goal_handle->cancel(); }
  2. 85% success Use a mutex to serialize cancel calls: std::lock_guard<std::mutex> lock(cancel_mutex_); if (!cancel_in_progress_) { cancel_in_progress_ = true; goal_handle->cancel(); cancel_in_progress_ = false; }
    Use a mutex to serialize cancel calls: std::lock_guard<std::mutex> lock(cancel_mutex_); if (!cancel_in_progress_) { cancel_in_progress_ = true; goal_handle->cancel(); cancel_in_progress_ = false; }

中文步骤

  1. 在取消前检查目标是否处于终端状态:if (goal_handle->get_status() == action_msgs::msg::GoalStatus::STATUS_ACCEPTED || goal_handle->get_status() == action_msgs::msg::GoalStatus::STATUS_EXECUTING) { goal_handle->cancel(); }
  2. 使用互斥锁序列化取消调用:std::lock_guard<std::mutex> lock(cancel_mutex_); if (!cancel_in_progress_) { cancel_in_progress_ = true; goal_handle->cancel(); cancel_in_progress_ = false; }

Dead Ends

Common approaches that don't work:

  1. 70% fail

    Race still occurs if two cancel calls happen within the sleep window; not a deterministic fix.

  2. 60% fail

    Error is suppressed but the action server state may remain inconsistent, leading to future crashes.