全局结构图

struct SteerQueue {
    std::queue<float> queue;        // 存储舵机角度值的队列
    std::mutex mtx;                 // 互斥锁保护队列
    std::condition_variable cv;     // 条件变量用于线程同步
    volatile bool stop_flag = false; // 线程停止标志
};

SteerQueue steer_queue;

# 🔹 std::queue<float> queue;

  • 作用:存储即将发送给舵机的角度值(如 65°、75°、85°)。
  • 典型流程:图像线程计算完角度后调用 steer_queue.queue.push(angle);舵机线程再从中读取 queue.front() 执行控制。

# 🔹 std::mutex mtx;

  • 作用:互斥锁,用于保护队列的读写,防止两个线程同时访问导致“数据竞争”或程序崩溃。

  • 使用方式

    std::lock_guard<std::mutex> lock(steer_queue.mtx);
    steer_queue.queue.push(angle);

# 🔹 std::condition_variable cv;

  • 作用:条件变量,用于通知舵机线程有新角度可以处理,否则舵机线程就一直阻塞、等待。

  • 工作流程

    1. 图像线程调用 cv.notify_one(); 通知舵机线程。

    2. 舵机线程使用 cv.wait(lock, 条件) 挂起等待新值。


# 🔹 volatile bool stop_flag = false;

  • 作用:控制舵机线程的停止条件。

  • volatile 关键词含义:告诉编译器这个变量可能会被其他线程修改,不要对它进行优化缓存,确保读取的是最新值。

  • 使用方式:当主程序要退出时设置 stop_flag = true;,舵机线程检测后退出循环:

    if (steer_queue.stop_flag) break;

  • 图像线程:负责分析图像并“投递”角度值;
  • 舵机线程:负责从队列中取出角度值并控制舵机;
  • 互斥锁 & 条件变量:确保线程之间安全地读写队列;
  • 停止标志:支持程序优雅地退出。
// 舵机控制线程函数
void steeringThread() {
    // 循环直到收到停止信号
    while (!steer_queue.stop_flag) {
        std::unique_lock<std::mutex> lock(steer_queue.mtx);
        // 等待条件:队列非空或停止标志置位
        steer_queue.cv.wait(lock, []{ 
            return !steer_queue.queue.empty() || steer_queue.stop_flag; 
        });

        // 检查退出条件
        if (steer_queue.stop_flag && steer_queue.queue.empty()) break;

        if (!steer_queue.queue.empty()) {
            // 优化策略:跳过所有积压指令,只处理最新角度
            float angle;
            while (!steer_queue.queue.empty()) {
                angle = steer_queue.queue.front(); // 获取队首
                steer_queue.queue.pop();           // 移除指令
            }
        
            lock.unlock(); // 提前释放锁,减少临界区时间
        
            // 调试输出(实际使用时可能注释掉)
            // printf("Steer_Angle = %d\n", static_cast<int>(angle));
            
            // 更新舵机PWM信号:将角度转换为占空比值
            update_duty(0, angle_to_duty(angle));
            
            // 控制舵机更新频率(200ms/5Hz)
            usleep(200000); // 200毫秒延时
        }
    }
}