rm_vision/tasks/omniperception/perceptron.cpp
2025-12-15 02:33:20 +08:00

107 lines
3.0 KiB
C++

#include "perceptron.hpp"
#include <chrono>
#include <memory>
#include <thread>
#include "tasks/auto_aim/yolo.hpp"
#include "tools/exiter.hpp"
#include "tools/logger.hpp"
namespace omniperception
{
Perceptron::Perceptron(
io::USBCamera * usbcam1, io::USBCamera * usbcam2, io::USBCamera * usbcam3,
io::USBCamera * usbcam4, const std::string & config_path)
: detection_queue_(10), decider_(config_path), stop_flag_(false)
{
// 初始化 YOLO 模型
yolo_parallel1_ = std::make_shared<auto_aim::YOLO>(config_path, false);
yolo_parallel2_ = std::make_shared<auto_aim::YOLO>(config_path, false);
yolo_parallel3_ = std::make_shared<auto_aim::YOLO>(config_path, false);
yolo_parallel4_ = std::make_shared<auto_aim::YOLO>(config_path, false);
std::this_thread::sleep_for(std::chrono::seconds(2));
// 创建四个线程进行并行推理
threads_.emplace_back([&] { parallel_infer(usbcam1, yolo_parallel1_); });
threads_.emplace_back([&] { parallel_infer(usbcam2, yolo_parallel2_); });
threads_.emplace_back([&] { parallel_infer(usbcam3, yolo_parallel3_); });
threads_.emplace_back([&] { parallel_infer(usbcam4, yolo_parallel4_); });
tools::logger()->info("Perceptron initialized.");
}
Perceptron::~Perceptron()
{
{
std::unique_lock<std::mutex> lock(mutex_);
stop_flag_ = true; // 设置退出标志
}
condition_.notify_all(); // 唤醒所有等待的线程
// 等待线程结束
for (auto & t : threads_) {
if (t.joinable()) {
t.join();
}
}
tools::logger()->info("Perceptron destructed.");
}
std::vector<DetectionResult> Perceptron::get_detection_queue()
{
std::vector<DetectionResult> result;
DetectionResult temp;
// 注意:这里的 pop 不阻塞(假设队列为空时会报错或忽略)
while (!detection_queue_.empty()) {
detection_queue_.pop(temp);
result.push_back(std::move(temp));
}
return result;
}
// 将并行推理逻辑移动到类成员函数
void Perceptron::parallel_infer(
io::USBCamera * cam, std::shared_ptr<auto_aim::YOLO> & yolov8_parallel)
{
if (!cam) {
tools::logger()->error("Camera pointer is null!");
return;
}
try {
while (true) {
cv::Mat usb_img;
std::chrono::steady_clock::time_point ts;
{
std::unique_lock<std::mutex> lock(mutex_);
if (stop_flag_) break; // 检查是否需要退出
}
cam->read(usb_img, ts);
if (usb_img.empty()) {
std::this_thread::sleep_for(std::chrono::milliseconds(30));
continue;
}
auto armors = yolov8_parallel->detect(usb_img);
if (!armors.empty()) {
auto delta_angle = decider_.delta_angle(armors, cam->device_name);
DetectionResult dr;
dr.armors = std::move(armors);
dr.timestamp = ts;
dr.delta_yaw = delta_angle[0] / 57.3;
dr.delta_pitch = delta_angle[1] / 57.3;
detection_queue_.push(dr); // 推入线程安全队列
}
}
} catch (const std::exception & e) {
tools::logger()->error("Exception in parallel_infer: {}", e.what());
}
}
} // namespace omniperception