feat(radar): 规范化 .data 立方体读取(position-major/16bit/字节序)
This commit is contained in:
parent
47e94592ce
commit
a9e2d98d15
|
|
@ -1,8 +1,12 @@
|
|||
#include "io/gpr/NormalizedRadarReader.hpp"
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
namespace geopro::io::gpr {
|
||||
namespace {
|
||||
std::map<std::string, std::string> parseKv(const std::string& text) {
|
||||
|
|
@ -64,4 +68,27 @@ double depthSpacingZ(const RadarHeader& h) {
|
|||
if (h.samples <= 1 || h.timeWindowNs <= 0.0) return 0.0;
|
||||
return (h.timeWindowNs / (h.samples - 1)) * waveVelocityMperNs(h) / 2.0;
|
||||
}
|
||||
std::vector<std::int16_t> readRadarDataCube(const std::string& dataPath,
|
||||
const RadarHeader& h) {
|
||||
if (h.bits != 16)
|
||||
throw std::runtime_error("readRadarDataCube: 暂仅支持 16-bit(BITS=" +
|
||||
std::to_string(h.bits) + " 待实现)");
|
||||
const std::size_t n = static_cast<std::size_t>(h.lastTrace) * h.samples;
|
||||
const std::uintmax_t expect = static_cast<std::uintmax_t>(n) * 2;
|
||||
std::error_code ec;
|
||||
const auto fsize = std::filesystem::file_size(dataPath, ec);
|
||||
if (ec || fsize != expect)
|
||||
throw std::runtime_error("规范化 .data 大小不符: " + dataPath);
|
||||
std::vector<std::int16_t> cube(n);
|
||||
std::ifstream f(dataPath, std::ios::binary);
|
||||
if (!f) throw std::runtime_error("打开 .data 失败: " + dataPath);
|
||||
f.read(reinterpret_cast<char*>(cube.data()), static_cast<std::streamsize>(expect));
|
||||
if (!f) throw std::runtime_error("读 .data 失败: " + dataPath);
|
||||
if (h.endianType == 2) // 大端 → 主机小端(x86),逐元素交换字节
|
||||
for (auto& v : cube) {
|
||||
const std::uint16_t u = static_cast<std::uint16_t>(v);
|
||||
v = static_cast<std::int16_t>((u >> 8) | (u << 8));
|
||||
}
|
||||
return cube;
|
||||
}
|
||||
} // namespace geopro::io::gpr
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef GEOPRO_IO_GPR_NORMALIZED_RADAR_READER_HPP
|
||||
#define GEOPRO_IO_GPR_NORMALIZED_RADAR_READER_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -30,6 +31,12 @@ double waveVelocityMperNs(const RadarHeader& h);
|
|||
// 深度采样间距(米): timeWindowNs/(samples-1) × 波速/2。samples<=1 → 0。
|
||||
double depthSpacingZ(const RadarHeader& h);
|
||||
|
||||
// 读规范化 .data → 扁平 int16 立方体,position-major 索引 ((t*M + c)*N + s)。
|
||||
// 按 header.bits/endianType 解码;P0 仅 16-bit(32-bit 抛 not implemented)。
|
||||
// 文件大小须 == lastTrace*samples*(bits/8),否则抛 std::runtime_error。
|
||||
std::vector<std::int16_t> readRadarDataCube(const std::string& dataPath,
|
||||
const RadarHeader& h);
|
||||
|
||||
} // namespace geopro::io::gpr
|
||||
|
||||
#endif // GEOPRO_IO_GPR_NORMALIZED_RADAR_READER_HPP
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include "io/gpr/NormalizedRadarReader.hpp"
|
||||
using namespace geopro::io::gpr;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
TEST(NormalizedRadarHead, ParsesCoreFieldsAndDerivesTraces) {
|
||||
const std::string head =
|
||||
|
|
@ -33,3 +37,37 @@ TEST(NormalizedRadarHead, DepthSpacingUsesDefaultVelocityWhenNoDielectric) {
|
|||
const double dz = depthSpacingZ(h);
|
||||
EXPECT_NEAR(dz, (96.419553 / 515.0) * 0.1 / 2.0, 1e-9);
|
||||
}
|
||||
|
||||
TEST(NormalizedRadarData, ReadsPositionMajorCubeLittleEndian) {
|
||||
// K=2 道, M=3 通道, N=2 采样; 值 v(t,c,s)=int16(100*t+10*c+s)。position-major 写。
|
||||
fs::path dir = fs::temp_directory_path() / "radar_data_test";
|
||||
fs::create_directories(dir);
|
||||
const fs::path dp = dir / "L.data";
|
||||
{
|
||||
std::ofstream f(dp, std::ios::binary);
|
||||
for (int t = 0; t < 2; ++t)
|
||||
for (int c = 0; c < 3; ++c)
|
||||
for (int s = 0; s < 2; ++s) {
|
||||
std::int16_t v = static_cast<std::int16_t>(100 * t + 10 * c + s);
|
||||
f.write(reinterpret_cast<const char*>(&v), sizeof(v)); // 小端(x86)
|
||||
}
|
||||
}
|
||||
geopro::io::gpr::RadarHeader h;
|
||||
h.samples = 2; h.channels = 3; h.lastTrace = 6; h.traces = 2; h.bits = 16; h.endianType = 1;
|
||||
const auto cube = geopro::io::gpr::readRadarDataCube(dp.string(), h);
|
||||
ASSERT_EQ(cube.size(), 2u * 3u * 2u);
|
||||
auto at = [&](int t, int c, int s) { return cube[(size_t(t) * 3 + c) * 2 + s]; };
|
||||
EXPECT_EQ(at(0, 0, 0), 0);
|
||||
EXPECT_EQ(at(1, 2, 1), 121); // 100+20+1
|
||||
EXPECT_EQ(at(0, 1, 0), 10);
|
||||
}
|
||||
|
||||
TEST(NormalizedRadarData, WrongFileSizeThrows) {
|
||||
fs::path dir = fs::temp_directory_path() / "radar_data_test";
|
||||
fs::create_directories(dir);
|
||||
const fs::path dp = dir / "bad.data";
|
||||
{ std::ofstream f(dp, std::ios::binary); std::int16_t v = 0; f.write((char*)&v, 2); }
|
||||
geopro::io::gpr::RadarHeader h;
|
||||
h.samples = 2; h.channels = 3; h.lastTrace = 6; h.traces = 2; h.bits = 16;
|
||||
EXPECT_THROW(geopro::io::gpr::readRadarDataCube(dp.string(), h), std::runtime_error);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue