Files
yq_2026_duo/wust_vision-main/tasks/auto_guidance/debug.cpp
2026-03-27 03:41:42 +08:00

295 lines
9.2 KiB
C++

#include "debug.hpp"
#include <fcntl.h>
#include <fmt/format.h>
#include <fstream>
#include <nlohmann/json.hpp>
#include <sys/mman.h>
#include <sys/stat.h>
namespace wust_vision {
namespace auto_guidance {
void drawAutoGuidanceDebugContent(cv::Mat& debug_img, const AutoGuidanceDebug& dbg) {
auto target = dbg.target;
auto lights = dbg.lights;
lights.drawFront(debug_img);
if (target.is_tracking_) {
auto now = std::chrono::steady_clock::now();
target.predict(now);
target.draw(debug_img);
}
std::string latency_str = fmt::format("Latency: {:.2f}ms", dbg.latency_ms);
cv::putText(
debug_img,
latency_str,
cv::Point(10, 30),
cv::FONT_HERSHEY_SIMPLEX,
0.8,
cv::Scalar(255, 255, 255),
2
);
cv::circle(
debug_img,
cv::Point2i(debug_img.cols / 2, debug_img.rows / 2),
5,
cv::Scalar(255, 255, 255),
2
);
double cx_norm = target.center().x / target.image_size_.width * 2.0 - 1.0;
double diff_center_norm = (target.is_tracking_) ? cx_norm : 0;
{
std::string diff_str = fmt::format("diff_cx_norm: {:.3f}", diff_center_norm);
int margin = 10;
int font_face = cv::FONT_HERSHEY_SIMPLEX;
double font_scale = 0.7;
int thickness = 2;
int baseline = 0;
cv::Size text_size =
cv::getTextSize(diff_str, font_face, font_scale, thickness, &baseline);
// 右上角文本左下角坐标
int x = debug_img.cols - margin - text_size.width;
int y = margin + text_size.height;
// 背景框,可选
cv::rectangle(
debug_img,
cv::Rect(
x - 5,
y - text_size.height - 5,
text_size.width + 10,
text_size.height + 10
),
cv::Scalar(0, 0, 0),
cv::FILLED,
cv::LINE_AA
);
cv::putText(
debug_img,
diff_str,
cv::Point(x, y),
font_face,
font_scale,
cv::Scalar(0, 255, 255),
thickness,
cv::LINE_AA
);
}
if (target.is_tracking_) {
const auto& s = target.target_state_;
std::string line1 =
fmt::format("pos: {:.1f} {:.1f} {:.1f} {:.1f}", s(0), s(2), s(4), s(6));
std::string line2 =
fmt::format("vel: {:.2f} {:.2f} {:.2f} {:.2f}", s(1), s(3), s(5), s(7));
int x = 10;
int y = debug_img.rows - 30; // 左下角位置
int dy = 28;
cv::putText(
debug_img,
line1,
cv::Point(x, y),
cv::FONT_HERSHEY_SIMPLEX,
0.75,
cv::Scalar(0, 255, 0),
2
);
cv::putText(
debug_img,
line2,
cv::Point(x, y + dy),
cv::FONT_HERSHEY_SIMPLEX,
0.75,
cv::Scalar(0, 255, 0),
2
);
double vx = s(1);
double vy = s(3);
cv::Point2f p0 = target.center();
double scale = 0.5;
cv::Point2f p1(p0.x + vx * scale, p0.y + vy * scale);
cv::arrowedLine(
debug_img,
p0,
p1,
cv::Scalar(0, 255, 0),
2,
cv::LINE_AA,
0,
0.25 // 箭头比例
);
}
}
void drawDebugOverlayWrite(const AutoGuidanceDebug& dbg, bool auto_fps) {
static auto last_show_time = std::chrono::steady_clock::now();
if (dbg.img_frame.src_img.empty())
return;
cv::Mat src_img = dbg.img_frame.src_img;
auto now = std::chrono::steady_clock::now();
const double min_interval_ms = 1000.0 / 30.0;
if (std::chrono::duration<double, std::milli>(now - last_show_time).count()
< min_interval_ms
&& auto_fps)
return;
last_show_time = now;
// 图像构造
cv::Mat debug_img;
src_img.convertTo(debug_img, -1, 1, 0);
cv::cvtColor(debug_img, debug_img, cv::COLOR_BGR2RGB);
if (debug_img.empty())
return;
// 封装后的绘图函数
drawAutoGuidanceDebugContent(debug_img, dbg);
cv::cvtColor(debug_img, debug_img, cv::COLOR_RGB2BGR);
// 编码写入共享内存路径
std::vector<uchar> buf;
cv::imencode(".jpg", debug_img, buf);
std::ofstream ofs("/dev/shm/debug_frame.jpg.tmp", std::ios::binary);
ofs.write(reinterpret_cast<const char*>(buf.data()), buf.size());
ofs.close();
std::rename("/dev/shm/debug_frame.jpg.tmp", "/dev/shm/debug_frame.jpg");
}
void drawDebugOverlayShm(const AutoGuidanceDebug& dbg, bool auto_fps) {
static auto last_show_time = std::chrono::steady_clock::now();
const char* shm_name = "/debug_frame";
const size_t shm_max_size = 2 * 1024 * 1024; // 2MB 最大图像编码缓存
if (dbg.img_frame.src_img.empty())
return;
cv::Mat src_img = dbg.img_frame.src_img;
auto now = std::chrono::steady_clock::now();
const double min_interval_ms = 1000.0 / 30.0;
if (std::chrono::duration<double, std::milli>(now - last_show_time).count()
< min_interval_ms
&& auto_fps)
return;
last_show_time = now;
// 复制并转RGB
cv::Mat debug_img;
src_img.convertTo(debug_img, -1, 1, 0);
cv::cvtColor(debug_img, debug_img, cv::COLOR_BGR2RGB);
if (debug_img.empty())
return;
// 绘制内容
drawAutoGuidanceDebugContent(debug_img, dbg);
// 编码为 JPG
std::vector<uchar> buf;
cv::imencode(".jpg", debug_img, buf);
size_t img_size = buf.size();
if (img_size > shm_max_size) {
std::cerr << "[drawDebugOverlayWrite] 图像过大: " << img_size << " bytes\n";
return;
}
// 创建/打开共享内存
int fd = shm_open(shm_name, O_CREAT | O_RDWR, 0666);
if (fd == -1) {
perror("shm_open failed");
return;
}
// 设置共享内存大小
if (ftruncate(fd, shm_max_size) == -1) {
perror("ftruncate failed");
close(fd);
return;
}
// 映射共享内存
void* ptr = mmap(nullptr, shm_max_size, PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap failed");
close(fd);
return;
}
// 写入图像数据
uint32_t size = static_cast<uint32_t>(img_size);
std::memcpy(ptr, &size, 4); // 前4字节写入长度
std::memcpy(static_cast<char*>(ptr) + 4, buf.data(), img_size);
// 关闭映射和文件描述符
munmap(ptr, shm_max_size);
close(fd);
}
void drawDebugOverlayShow(const AutoGuidanceDebug& dbg, bool auto_fps) {
static auto last_show_time = std::chrono::steady_clock::now();
if (dbg.img_frame.src_img.empty())
return;
cv::Mat src_img = dbg.img_frame.src_img;
auto now = std::chrono::steady_clock::now();
const double min_interval_ms = 1000.0 / 30.0;
if (std::chrono::duration<double, std::milli>(now - last_show_time).count()
< min_interval_ms
&& auto_fps)
return;
last_show_time = now;
// 图像构造
cv::Mat debug_img;
src_img.convertTo(debug_img, -1, 1, 0);
cv::cvtColor(debug_img, debug_img, cv::COLOR_BGR2RGB);
if (debug_img.empty())
return;
// 封装后的绘图函数
drawAutoGuidanceDebugContent(debug_img, dbg);
cv::imshow("debug_armor", debug_img);
cv::waitKey(1);
}
void debuglog(const GuidanceTarget& target) {
static bool first_log = true;
static std::chrono::steady_clock::time_point start_time;
static DebugLogs log;
if (first_log) {
start_time = std::chrono::steady_clock::now();
first_log = false;
}
auto now = std::chrono::steady_clock::now();
double t = std::chrono::duration<double>(now - start_time).count();
log.time_log.push_back(t);
double cx_norm = target.center().x / target.image_size_.width * 2.0 - 1.0;
log.cx_log.push_back(cx_norm);
auto trim = [](std::vector<double>& v) {
if (v.size() > 1000)
v.erase(v.begin());
};
trim(log.time_log);
trim(log.cx_log);
nlohmann::json j;
{
j["time"] = log.time_log;
j["yaw"] = log.cx_log;
}
std::ofstream file("/dev/shm/cmd_log.json");
if (file.is_open()) {
file << j.dump();
}
}
} // namespace auto_guidance
} // namespace wust_vision