3D
This commit is contained in:
+151
-19
@@ -12,6 +12,7 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include "Core/Base/JSON.h"
|
||||
#include "Core/Base/ThreadManager.h"
|
||||
#include "Core/Base/global_include.h"
|
||||
@@ -21,6 +22,21 @@
|
||||
#include "Core/Base/SM_RingBuffer.h"
|
||||
#include "Dll_Global.h"
|
||||
#include <string_view>
|
||||
#ifndef ECAP_ADSB_PLAYBACK_SPEED_RATE
|
||||
#define ECAP_ADSB_PLAYBACK_SPEED_RATE 20.0
|
||||
#endif
|
||||
#ifndef ECAP_ADSB_PLAYBACK_LOOP
|
||||
#define ECAP_ADSB_PLAYBACK_LOOP 1
|
||||
#endif
|
||||
#ifndef ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME
|
||||
#define ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME 1
|
||||
#endif
|
||||
#ifndef ECAP_ADSB_PLAYBACK_MAX_BATCH_LINES
|
||||
#define ECAP_ADSB_PLAYBACK_MAX_BATCH_LINES 512
|
||||
#endif
|
||||
#ifndef ECAP_ADSB_PLAYBACK_FALLBACK_LINE_INTERVAL_SEC
|
||||
#define ECAP_ADSB_PLAYBACK_FALLBACK_LINE_INTERVAL_SEC 0.02
|
||||
#endif
|
||||
std::vector<std::string> ddd = {
|
||||
"1A 33 1A 1A F1 DA 08 2A 73 60 8D 78 12 0A EA 28 88 64 25 3C 08 33 22 41",
|
||||
"1A 33 1A 1A F1 D9 13 EA E7 11 8D 78 1D 40 58 BF 41 E2 45 49 09 7B C8 24",
|
||||
@@ -48,33 +64,64 @@ std::string get_absb() {
|
||||
}
|
||||
class TextLineReader {
|
||||
public:
|
||||
struct Playback_Line {
|
||||
std::string text;
|
||||
double virtual_second{};
|
||||
};
|
||||
explicit TextLineReader(std::string_view file_path) {
|
||||
load(file_path);
|
||||
}
|
||||
// 每调用一次,返回一行
|
||||
// 返回 true 表示成功取到一行
|
||||
// 返回 false 表示已经没有更多行
|
||||
bool get(std::string& ret_line) {
|
||||
if (index_ >= lines_.size()) {
|
||||
return false;
|
||||
std::size_t read(char* buf, std::size_t len) {
|
||||
if (lines_.empty() || len == 0) {
|
||||
return 0;
|
||||
}
|
||||
ret_line = lines_[index_];
|
||||
++index_;
|
||||
return true;
|
||||
std::string ret;
|
||||
std::size_t count = 0;
|
||||
while (count < ECAP_ADSB_PLAYBACK_MAX_BATCH_LINES) {
|
||||
if (index_ >= lines_.size()) {
|
||||
if (ECAP_ADSB_PLAYBACK_LOOP) {
|
||||
reset();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!line_ready(lines_[index_])) {
|
||||
break;
|
||||
}
|
||||
const auto& line = lines_[index_].text;
|
||||
auto next_size = ret.size() + line.size() + 1;
|
||||
if (!ret.empty() && next_size > len) {
|
||||
break;
|
||||
}
|
||||
ret += line;
|
||||
ret += '\n';
|
||||
++index_;
|
||||
++count;
|
||||
if (!ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto copy_size = ret.size();
|
||||
if (copy_size > len) {
|
||||
copy_size = len;
|
||||
}
|
||||
std::memcpy(buf, ret.data(), copy_size);
|
||||
return copy_size;
|
||||
}
|
||||
// 重新从第一行开始读
|
||||
void reset() {
|
||||
index_ = 0;
|
||||
true_start_time_ = clock::now();
|
||||
start_virtual_second_ = lines_.empty() ? 0 : lines_.front().virtual_second;
|
||||
}
|
||||
// 总行数
|
||||
std::size_t size() const {
|
||||
return lines_.size();
|
||||
}
|
||||
// 是否已经读完
|
||||
bool empty() const {
|
||||
return lines_.empty();
|
||||
}
|
||||
private:
|
||||
using clock = std::chrono::steady_clock;
|
||||
void load(std::string_view file_path) {
|
||||
std::ifstream file{std::string(file_path)};
|
||||
// std::cout << "抛出异常" << std::endl;
|
||||
@@ -86,21 +133,106 @@ private:
|
||||
throw std::runtime_error(err);
|
||||
}
|
||||
std::string line;
|
||||
std::optional<double> last_day_second;
|
||||
std::uint64_t day_offset = 0;
|
||||
std::size_t fallback_index = 0;
|
||||
while (std::getline(file, line)) {
|
||||
lines_.push_back(line);
|
||||
auto day_second = parse_day_second(line);
|
||||
if (!day_second.has_value()) {
|
||||
day_second = fallback_index * ECAP_ADSB_PLAYBACK_FALLBACK_LINE_INTERVAL_SEC;
|
||||
}
|
||||
if (last_day_second.has_value() && day_second.value() + 3600.0 < last_day_second.value()) {
|
||||
++day_offset;
|
||||
}
|
||||
lines_.push_back({line, day_offset * 86400.0 + day_second.value()});
|
||||
last_day_second = day_second;
|
||||
++fallback_index;
|
||||
}
|
||||
index_ = 0;
|
||||
reset();
|
||||
}
|
||||
bool line_ready(const Playback_Line& line) const {
|
||||
if (!ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME) {
|
||||
return true;
|
||||
}
|
||||
return line.virtual_second <= current_virtual_second();
|
||||
}
|
||||
double current_virtual_second() const {
|
||||
auto elapsed = std::chrono::duration<double>(clock::now() - true_start_time_).count();
|
||||
return start_virtual_second_ + elapsed * ECAP_ADSB_PLAYBACK_SPEED_RATE;
|
||||
}
|
||||
static std::optional<double> parse_day_second(std::string_view line) {
|
||||
auto bytes = parse_hex_bytes(line);
|
||||
if (!bytes.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto packet = unescape_packet(bytes.value());
|
||||
if (packet.size() < 8 || packet[0] != 0x1a) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::uint64_t raw = 0;
|
||||
for (std::size_t i = 2; i < 8; ++i) {
|
||||
raw = (raw << 8) | packet[i];
|
||||
}
|
||||
auto daysec = static_cast<std::uint32_t>((raw >> 30) & 0x3ffff);
|
||||
auto nanosec = static_cast<std::uint32_t>(raw & 0x3fffffff);
|
||||
return daysec + nanosec / 1000000000.0;
|
||||
}
|
||||
static std::optional<std::vector<std::uint8_t>> parse_hex_bytes(std::string_view line) {
|
||||
std::vector<std::uint8_t> ret;
|
||||
int high = -1;
|
||||
for (char ch : line) {
|
||||
int value = hex_value(ch);
|
||||
if (value < 0) {
|
||||
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
|
||||
continue;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
if (high < 0) {
|
||||
high = value;
|
||||
}
|
||||
else {
|
||||
ret.push_back(static_cast<std::uint8_t>((high << 4) | value));
|
||||
high = -1;
|
||||
}
|
||||
}
|
||||
if (high >= 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int hex_value(char ch) {
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
return ch - '0';
|
||||
}
|
||||
if (ch >= 'a' && ch <= 'f') {
|
||||
return ch - 'a' + 10;
|
||||
}
|
||||
if (ch >= 'A' && ch <= 'F') {
|
||||
return ch - 'A' + 10;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
static std::vector<std::uint8_t> unescape_packet(const std::vector<std::uint8_t>& bytes) {
|
||||
std::vector<std::uint8_t> ret;
|
||||
ret.reserve(bytes.size());
|
||||
for (std::size_t i = 0; i < bytes.size(); ++i) {
|
||||
ret.push_back(bytes[i]);
|
||||
if (bytes[i] == 0x1a && i + 1 < bytes.size() && bytes[i + 1] == 0x1a) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
std::vector<std::string> lines_;
|
||||
std::vector<Playback_Line> lines_;
|
||||
std::size_t index_ = 0;
|
||||
clock::time_point true_start_time_{clock::now()};
|
||||
double start_virtual_second_ = 0;
|
||||
};
|
||||
std::size_t adsb_read(char* buf, std::size_t len) {
|
||||
static TextLineReader reader(get_exe_dir() + "/ADS-B_195_0205.txt");
|
||||
std::string line;
|
||||
reader.get(line);
|
||||
auto l = line.size();
|
||||
std::memcpy(buf, line.c_str(), l);
|
||||
auto l = reader.read(buf, len);
|
||||
/*static Frequency_Limit fl;
|
||||
if (fl.test()) {
|
||||
std::cout << "adsb_read" << VAR_STR_2(l, len) << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user