Skip to content

Failed pair-opt attempts bypass the attempt cooldown and are retried at timer frequency #51

Description

@LBJ318

Problem Description

The pair-opt mechanism uses recent_attempt_time_ and attempt_interval_ to prevent repeated pair-opt attempts within a short period:

if (tn - state1.recent_attempt_time_ < fp_->attempt_interval_)
  return;

However, when pair-opt determines that the reallocated assignment has a higher cost, the callback returns immediately:

if (cur_app1 + cur_app2 > prev_app1 + prev_app2 + 0.1) {
  ROS_ERROR("Larger cost after reallocation");
  if (state_ != WAIT_TRIGGER) {
    return;
  }
}

The timestamp used by the cooldown mechanism is updated only later:

state1.recent_attempt_time_ = tn;

Therefore, when execution follows the Larger cost after reallocation branch, optTimerCallback() returns before updating recent_attempt_time_.

The failed attempt is not recorded by the cooldown mechanism. On the next timer callback, the same pair-opt attempt can immediately pass the cooldown check, fail again, and print the same error.

This results in failed pair-opt attempts being repeatedly executed at timer frequency.

Execution Flow

optTimerCallback is triggered
        ↓
The cooldown check passes
        ↓
pair-opt reallocation is calculated
        ↓
The reallocated cost is higher
        ↓
"Larger cost after reallocation"
        ↓
The callback returns directly
        ↓
recent_attempt_time_ is not updated
        ↓
The next timer callback passes the cooldown check again
        ↓
The failed pair-opt is repeatedly retried

Suggested Fix

Update the cooldown timestamp when a pair-opt attempt starts, rather than only after a valid PairOpt request has been generated.

For example:

if (tn - state1.recent_attempt_time_ < fp_->attempt_interval_)
  return;

// Record every pair-opt attempt, including rejected attempts.
state1.recent_attempt_time_ = tn;

The reallocation-cost check can then be performed afterward:

if (cur_app1 + cur_app2 > prev_app1 + prev_app2 + 0.1) {
  ROS_ERROR("Larger cost after reallocation");
  if (state_ != WAIT_TRIGGER) {
    return;
  }
}

This ensures that successful, rejected, and failed pair-opt attempts are all limited by attempt_interval_.

If pair-opt modifies the shared state of two drones, the cooldown state of the participating drone should also be updated according to the existing protocol, preventing the other drone from immediately initiating another attempt for the same pair.

The implementation may also distinguish between the most recent attempt and the most recent successful reallocation:

recent_attempt_time_  // Most recent pair-opt attempt
recent_success_time_  // Most recent successful reallocation

recent_attempt_time_ should limit all attempts, including higher-cost reallocations, invalid targets, and request failures.

recent_success_time_ should only record successful task reallocations.

For repeatedly failing pairs, an additional backoff mechanism may be used:

First failure:
wait for attempt_interval_

Repeated failures:
gradually increase the retry interval

Failure threshold reached:
temporarily block the pair or invalidate the current target

This preserves the recovery capability of pair-opt while preventing repeated failed reallocations from consuming CPU, flooding logs, and repeatedly interfering with the FSM.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions