You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
5.4 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// lidar_utils.cpp - 雷达连接与扫描采集实现
#include "lidar_utils.h"
#include "config.h"
#include "filter.h"
#include <cmath>
#include <iostream>
// ==================== 雷达连接 ====================
bool connect_lidar(pavo2::pavo2_driver& driver)
{
driver.set_conn_protocol(pavo2::PAVO2_PROTO_TYPE::TCP);
std::cout << "[连接] 正在连接雷达 " << Leida_IP << ":" << Leida_PORT << " ..." << std::endl;
if (!driver.pavo2_open(Leida_IP, Leida_PORT, OPEN_TIMEOUT_MS))
{
std::cerr << "[错误] 连接雷达失败!请检查IP和网络连接。" << std::endl;
return false;
}
std::cout << "[连接] 雷达连接成功!" << std::endl;
driver.enable_tail_filter(Tuo_Wei);
driver.enable_front_filter(Qian_Chong);
driver.enable_far_hr_filter(Yuan_Duan);
driver.enable_near_hr(Jin_Duan);
std::string sn, pn, sdk_ver, fw_ver;
if (driver.get_device_sn(sn))
std::cout << "[信息] 设备SN: " << sn << std::endl;
if (driver.get_device_pn(pn))
std::cout << "[信息] 设备PN: " << pn << std::endl;
if (driver.get_sdk_ver(sdk_ver))
std::cout << "[信息] SDK版本: " << sdk_ver << std::endl;
if (driver.get_firmware_ver(fw_ver))
std::cout << "[信息] 固件版本: " << fw_ver << std::endl;
if (!driver.enable_data(true))
{
std::cerr << "[错误] 开启数据传输失败!" << std::endl;
return false;
}
std::cout << "[信息] 雷达数据传输已开启。" << std::endl;
return true;
}
// ==================== 扫描辅助 ====================
int drain_stale_scans(pavo2::pavo2_driver& driver, int max_ms)
{
pavo2::pavo_packet_info_scan_t tmp;
int flushed = 0;
auto flush_begin = std::chrono::steady_clock::now();
while (true)
{
if (driver.get_scans_available() <= 0) break;
if (!driver.get_scanned_data(tmp, 0)) break; // 0ms = 立即返回,不阻塞
flushed++;
if (std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - flush_begin).count() > max_ms)
break;
}
return flushed;
}
double z_for_elapsed(double elapsed_ms)
{
return (Speed_Z > 0)
? (Speed_Z * 10.0 * elapsed_ms / 1000.0) // cm/s ×10 = mm/s, ×秒 = mm
: (double)elapsed_ms;
}
size_t scan_convert_points(const pavo2::pavo_packet_info_scan_t& scan_info,
double z_val, std::vector<CountPoint>& out)
{
size_t before = out.size();
for (const auto& s : scan_info.vec_buff)
{
double angle_deg = s.angle / 100.0;
double angle_rad = angle_deg * 3.14159265 / 180.0;
double x_mm = s.distance * sin(angle_rad) * 2.0;
double y_mm = -s.distance * cos(angle_rad) * 2.0;
if (!xy_filter_allowed(x_mm, y_mm)) continue;
out.push_back({x_mm, y_mm, z_val});
}
return out.size() - before;
}
// ==================== 扫描会话 ====================
bool ScanSession::start(pavo2::pavo2_driver& driver)
{
{
std::lock_guard<std::mutex> lk(mtx_);
if (running_) return false;
running_ = true;
stop_req_ = false;
}
try
{
th_ = std::thread(&ScanSession::collect_loop, this, &driver);
return true;
}
catch (...)
{
std::lock_guard<std::mutex> lk(mtx_);
running_ = false;
stop_req_ = false;
return false;
}
}
size_t ScanSession::stop()
{
{
std::lock_guard<std::mutex> lk(mtx_);
if (!running_) return points_.size();
stop_req_ = true;
}
if (th_.joinable()) th_.join();
std::lock_guard<std::mutex> lk(mtx_);
running_ = false;
return points_.size();
}
std::vector<CountPoint> ScanSession::snapshot() const
{
std::lock_guard<std::mutex> lk(mtx_);
return points_;
}
bool ScanSession::running() const
{
std::lock_guard<std::mutex> lk(mtx_);
return running_;
}
void ScanSession::reset()
{
std::lock_guard<std::mutex> lk(mtx_);
points_.clear();
running_ = false;
stop_req_ = false;
}
void ScanSession::collect_loop(pavo2::pavo2_driver* driver)
{
// 排空积压:丢弃 SDK 缓存中 start 之前雷达已转出的旧数据包。
// 否则旧包会在图像开头 z 方向挤成一段密集点;排空完成才开始计时。
int flushed = drain_stale_scans(*driver);
{
std::lock_guard<std::mutex> lk(mtx_);
if (stop_req_) return; // 排空期间被 stop,直接退出
start_tp_ = std::chrono::steady_clock::now(); // 排空完成才开始计时
}
if (flushed > 0)
std::cout << "[lidar] 已丢弃积压扫描包 " << flushed << " 个" << std::endl;
while (true)
{
pavo2::pavo_packet_info_scan_t scan_info;
if (driver->get_scanned_data(scan_info, 100)) // 100ms超时轮询,可及时响应stop
{
auto now = std::chrono::steady_clock::now();
double elapsed_ms = (double)std::chrono::duration_cast<std::chrono::milliseconds>(
now - start_tp_).count();
double z_val = z_for_elapsed(elapsed_ms);
std::lock_guard<std::mutex> lk(mtx_);
if (stop_req_) break;
scan_convert_points(scan_info, z_val, points_);
}
else
{
std::lock_guard<std::mutex> lk(mtx_);
if (stop_req_) break;
}
}
}