常规更新
This commit is contained in:
@@ -1 +1,2 @@
|
||||
/readsb/
|
||||
/old/
|
||||
|
||||
@@ -435,7 +435,6 @@ D_BDS(60) // 航向和速度报告
|
||||
// Commb MS Meteorological services
|
||||
D_BDS(44) // 气象例行空气报告
|
||||
D_BDS(45) // 气象灾害报告
|
||||
// TODO: 1111
|
||||
#define CE(cond, msg) \
|
||||
if (cond) { \
|
||||
static Log_Type log_type({}, {{"POS", LOG_POS}}); \
|
||||
|
||||
+673
-90
@@ -1,4 +1,5 @@
|
||||
#include "./Common.h"
|
||||
#include "Core/Statistics/Frequency_Limit.h"
|
||||
#include "SSR/CPR/CPR.h"
|
||||
#undef max
|
||||
#undef min
|
||||
@@ -1957,118 +1958,700 @@ std::string infer(const std::string& msg_bin, bool mrar) {
|
||||
});
|
||||
return result.empty() ? "" : std::string(result);
|
||||
}
|
||||
std::vector<std::string> infer_old(const std::string& msg, bool mrar) {
|
||||
auto df = SSR::decode_df(msg);
|
||||
if (allzeros(msg)) {
|
||||
return {};
|
||||
static bool bds_bit(const std::string& msg, int bit) {
|
||||
return msg[bit - 1] == '1';
|
||||
}
|
||||
static unsigned long long bds_bits(const std::string& msg, int first, int last) {
|
||||
return bin2<unsigned long long>(msg.substr(first - 1, last - first + 1));
|
||||
}
|
||||
static int bds10_score(const std::string& msg) {
|
||||
if (bds_bits(msg, 1, 8) != 0x10) {
|
||||
return 0;
|
||||
}
|
||||
// For ADS-B / Mode-S extended squitter
|
||||
if (df == Downlink_Format::Extended_Squitter_17) {
|
||||
auto tc = type_code(msg);
|
||||
if (!tc) {
|
||||
return {};
|
||||
if (bds_bits(msg, 10, 14) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return 56;
|
||||
}
|
||||
static int bds17_score(const std::string& msg) {
|
||||
if (bds_bits(msg, 25, 56) != 0) {
|
||||
return 0;
|
||||
}
|
||||
int score = 0;
|
||||
if (bds_bit(msg, 7)) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
score -= 2;
|
||||
}
|
||||
if (bds_bit(msg, 10)) {
|
||||
score -= 2;
|
||||
}
|
||||
if (bds_bit(msg, 11)) {
|
||||
score -= 2;
|
||||
}
|
||||
if (bds_bit(msg, 12)) {
|
||||
score -= 2;
|
||||
}
|
||||
if (bds_bit(msg, 13)) {
|
||||
score -= 2;
|
||||
}
|
||||
if (bds_bit(msg, 14)) {
|
||||
score -= 2;
|
||||
}
|
||||
if (bds_bit(msg, 20)) {
|
||||
score -= 2;
|
||||
}
|
||||
if (bds_bit(msg, 21)) {
|
||||
score -= 2;
|
||||
}
|
||||
if (bds_bit(msg, 22)) {
|
||||
score -= 2;
|
||||
}
|
||||
if (bds_bit(msg, 1) && bds_bit(msg, 2) && bds_bit(msg, 3) && bds_bit(msg, 4) && bds_bit(msg, 5)) {
|
||||
score += 5;
|
||||
if (bds_bit(msg, 6)) {
|
||||
score += 1;
|
||||
}
|
||||
if (tc >= 1 && tc <= 4) return {"08"}; // identification and category
|
||||
if (tc >= 5 && tc <= 8) return {"06"}; // surface movement
|
||||
if (tc >= 9 && tc <= 18) return {"05"}; // airborne position, baro-alt
|
||||
if (tc == 19) return {"09"}; // airborne velocity
|
||||
if (tc >= 20 && tc <= 22) return {"05"}; // airborne position, gnss-alt
|
||||
if (tc == 28) return {"61"}; // aircraft status
|
||||
if (tc == 29) return {"62"}; // target state and status
|
||||
if (tc == 31) return {"65"}; // operational status
|
||||
}
|
||||
// For Comm-B replies
|
||||
bool IS10 = is10(msg);
|
||||
bool IS17 = is17(msg);
|
||||
bool IS20 = is20(msg);
|
||||
bool IS30 = is30(msg);
|
||||
bool IS40 = is40(msg);
|
||||
bool IS50 = is50(msg);
|
||||
bool IS60 = is60(msg);
|
||||
bool IS44 = is44(msg);
|
||||
bool IS45 = is45(msg);
|
||||
std::vector<std::string> bds_result;
|
||||
if (mrar) {
|
||||
std::array<std::string, 9> allbds = {
|
||||
"10", "17", "20", "30", "40",
|
||||
"44", "45", "50", "60"
|
||||
};
|
||||
bool mask[] = {IS10, IS17, IS20, IS30, IS40, IS44, IS45, IS50, IS60};
|
||||
for (size_t i = 0; i < 9; ++i) {
|
||||
if (mask[i]) {
|
||||
bds_result.push_back(allbds[i]);
|
||||
}
|
||||
else if (!bds_bit(msg, 1) && !bds_bit(msg, 2) && !bds_bit(msg, 3) && !bds_bit(msg, 4) && !bds_bit(msg, 5) && !bds_bit(msg, 6)) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
score -= 12;
|
||||
}
|
||||
if (bds_bit(msg, 16) && bds_bit(msg, 24)) {
|
||||
score += 2;
|
||||
if (bds_bit(msg, 9)) {
|
||||
score += 1;
|
||||
}
|
||||
}
|
||||
else if (!bds_bit(msg, 16) && !bds_bit(msg, 24) && !bds_bit(msg, 9)) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
score -= 6;
|
||||
}
|
||||
return score;
|
||||
}
|
||||
static int bds20_score(const std::string& msg) {
|
||||
if (bds_bits(msg, 1, 8) != 0x20) {
|
||||
return 0;
|
||||
}
|
||||
const std::string chars = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?";
|
||||
int score = 8;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
char ch = chars[bds_bits(msg, 9 + i * 6, 14 + i * 6)];
|
||||
if ((ch >= 'A' && ch <= 'Z') || (ch >= '-' && ch <= '9') || ch == ' ' || ch == '@') {
|
||||
score += 6;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
static int bds30_score(const std::string& msg) {
|
||||
if (bds_bits(msg, 1, 8) != 0x30) {
|
||||
return 0;
|
||||
}
|
||||
return 56;
|
||||
}
|
||||
static int bds40_score(const std::string& msg) {
|
||||
unsigned mcp_valid = bds_bit(msg, 1);
|
||||
unsigned mcp_raw = bds_bits(msg, 2, 13);
|
||||
unsigned fms_valid = bds_bit(msg, 14);
|
||||
unsigned fms_raw = bds_bits(msg, 15, 26);
|
||||
unsigned baro_valid = bds_bit(msg, 27);
|
||||
unsigned baro_raw = bds_bits(msg, 28, 39);
|
||||
unsigned reserved_1 = bds_bits(msg, 40, 47);
|
||||
unsigned mode_valid = bds_bit(msg, 48);
|
||||
unsigned mode_raw = bds_bits(msg, 49, 51);
|
||||
unsigned reserved_2 = bds_bits(msg, 52, 53);
|
||||
unsigned source_valid = bds_bit(msg, 54);
|
||||
unsigned source_raw = bds_bits(msg, 55, 56);
|
||||
if (!mcp_valid && !fms_valid && !baro_valid && !mode_valid && !source_valid) {
|
||||
return 0;
|
||||
}
|
||||
int score = 0;
|
||||
unsigned mcp_alt = 0;
|
||||
if (mcp_valid && mcp_raw != 0) {
|
||||
mcp_alt = mcp_raw * 16;
|
||||
if (mcp_alt >= 1000 && mcp_alt <= 50000) {
|
||||
score += 13;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!mcp_valid && mcp_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
unsigned fms_alt = 0;
|
||||
if (fms_valid && fms_raw != 0) {
|
||||
fms_alt = fms_raw * 16;
|
||||
if (fms_alt >= 1000 && fms_alt <= 50000) {
|
||||
score += 13;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!fms_valid && fms_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
double baro_setting = 0;
|
||||
if (baro_valid && baro_raw != 0) {
|
||||
baro_setting = 800 + baro_raw * 0.1;
|
||||
if (baro_setting >= 900 && baro_setting <= 1100) {
|
||||
score += 13;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!baro_valid && baro_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
if (reserved_1 != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (mode_valid) {
|
||||
score += 4;
|
||||
}
|
||||
else if (!mode_valid && mode_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
if (reserved_2 != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (source_valid) {
|
||||
score += 3;
|
||||
}
|
||||
else if (!source_valid && source_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
if (mcp_valid && fms_valid && mcp_alt != fms_alt) {
|
||||
score -= 4;
|
||||
}
|
||||
if (mcp_valid) {
|
||||
unsigned remainder = mcp_alt % 500;
|
||||
if (!(remainder < 16 || remainder > 484)) {
|
||||
score -= 4;
|
||||
}
|
||||
}
|
||||
if (fms_valid) {
|
||||
unsigned remainder = fms_alt % 500;
|
||||
if (!(remainder < 16 || remainder > 484)) {
|
||||
score -= 4;
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
static int bds50_score(const std::string& msg) {
|
||||
unsigned roll_valid = bds_bit(msg, 1);
|
||||
unsigned roll_sign = bds_bit(msg, 2);
|
||||
unsigned roll_raw = bds_bits(msg, 3, 11);
|
||||
unsigned track_valid = bds_bit(msg, 12);
|
||||
unsigned track_sign = bds_bit(msg, 13);
|
||||
unsigned track_raw = bds_bits(msg, 14, 23);
|
||||
unsigned gs_valid = bds_bit(msg, 24);
|
||||
unsigned gs_raw = bds_bits(msg, 25, 34);
|
||||
unsigned track_rate_valid = bds_bit(msg, 35);
|
||||
unsigned track_rate_sign = bds_bit(msg, 36);
|
||||
unsigned track_rate_raw = bds_bits(msg, 37, 45);
|
||||
unsigned tas_valid = bds_bit(msg, 46);
|
||||
unsigned tas_raw = bds_bits(msg, 47, 56);
|
||||
if (!roll_valid || !track_valid || !gs_valid || !tas_valid) {
|
||||
return 0;
|
||||
}
|
||||
int score = 0;
|
||||
double roll = 0;
|
||||
if (roll_valid) {
|
||||
roll = roll_raw * 45.0 / 256.0;
|
||||
if (roll_sign) {
|
||||
roll -= 90.0;
|
||||
}
|
||||
if (roll >= -40 && roll < 40) {
|
||||
score += 11;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!roll_valid && roll_raw == 0 && !roll_sign) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
if (track_valid) {
|
||||
score += 12;
|
||||
}
|
||||
else if (!track_valid && track_raw == 0 && !track_sign) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
unsigned gs = 0;
|
||||
if (gs_valid && gs_raw != 0) {
|
||||
gs = gs_raw * 2;
|
||||
if (gs >= 50 && gs <= 700) {
|
||||
score += 11;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!gs_valid && gs_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
double track_rate = 0;
|
||||
if (track_rate_valid) {
|
||||
track_rate = track_rate_raw * 8.0 / 256.0;
|
||||
if (track_rate_sign) {
|
||||
track_rate -= 16;
|
||||
}
|
||||
if (track_rate >= -10.0 && track_rate <= 10.0) {
|
||||
score += 11;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!track_rate_valid && track_rate_raw == 0 && !track_rate_sign) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
unsigned tas = 0;
|
||||
if (tas_valid && tas_raw != 0) {
|
||||
tas = tas_raw * 2;
|
||||
if (tas >= 50 && tas <= 700) {
|
||||
score += 11;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!tas_valid && tas_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
if (gs_valid && tas_valid) {
|
||||
int delta = abs((int)gs_valid - (int)tas_valid);
|
||||
if (delta > 150) {
|
||||
score -= 6;
|
||||
}
|
||||
}
|
||||
if (roll_valid && tas_valid && tas > 0 && track_rate_valid) {
|
||||
double turn_rate = 68625 * tan(roll * PI / 180.0) / (tas * 20 * PI);
|
||||
double delta = fabs(turn_rate - track_rate);
|
||||
if (delta > 2.0) {
|
||||
score -= 6;
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
static int bds60_score(const std::string& msg) {
|
||||
unsigned heading_valid = bds_bit(msg, 1);
|
||||
unsigned heading_sign = bds_bit(msg, 2);
|
||||
unsigned heading_raw = bds_bits(msg, 3, 12);
|
||||
unsigned ias_valid = bds_bit(msg, 13);
|
||||
unsigned ias_raw = bds_bits(msg, 14, 23);
|
||||
unsigned mach_valid = bds_bit(msg, 24);
|
||||
unsigned mach_raw = bds_bits(msg, 25, 34);
|
||||
unsigned baro_rate_valid = bds_bit(msg, 35);
|
||||
unsigned baro_rate_sign = bds_bit(msg, 36);
|
||||
unsigned baro_rate_raw = bds_bits(msg, 37, 45);
|
||||
unsigned inertial_rate_valid = bds_bit(msg, 46);
|
||||
unsigned inertial_rate_sign = bds_bit(msg, 47);
|
||||
unsigned inertial_rate_raw = bds_bits(msg, 48, 56);
|
||||
if (!heading_valid || !ias_valid || !mach_valid || (!baro_rate_valid && !inertial_rate_valid)) {
|
||||
return 0;
|
||||
}
|
||||
int score = 0;
|
||||
if (heading_valid) {
|
||||
score += 12;
|
||||
}
|
||||
else if (!heading_valid && heading_raw == 0 && !heading_sign) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
if (ias_valid && ias_raw != 0) {
|
||||
if (ias_raw >= 50 && ias_raw <= 700) {
|
||||
score += 11;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!ias_valid && ias_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
double mach = 0;
|
||||
if (mach_valid && mach_raw != 0) {
|
||||
mach = mach_raw * 2.048 / 512;
|
||||
if (mach >= 0.1 && mach <= 0.9) {
|
||||
score += 11;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!mach_valid && mach_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
int baro_rate = 0;
|
||||
if (baro_rate_valid) {
|
||||
baro_rate = baro_rate_raw * 32;
|
||||
if (baro_rate_sign) {
|
||||
baro_rate -= 16384;
|
||||
}
|
||||
if (baro_rate >= -6000 && baro_rate <= 6000) {
|
||||
score += 11;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!baro_rate_valid && baro_rate_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
int inertial_rate = 0;
|
||||
if (inertial_rate_valid) {
|
||||
inertial_rate = inertial_rate_raw * 32;
|
||||
if (inertial_rate_sign) {
|
||||
inertial_rate -= 16384;
|
||||
}
|
||||
if (inertial_rate >= -6000 && inertial_rate <= 6000) {
|
||||
score += 11;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!inertial_rate_valid && inertial_rate_raw == 0) {
|
||||
score += 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
if (baro_rate_valid && inertial_rate_valid) {
|
||||
int delta = abs(baro_rate - inertial_rate);
|
||||
if (delta > 2000) {
|
||||
score -= 12;
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
static int bds44_score(const std::string& msg) {
|
||||
unsigned source = bds_bits(msg, 1, 4);
|
||||
unsigned wind_valid = bds_bit(msg, 5);
|
||||
unsigned wind_speed_raw = bds_bits(msg, 6, 14);
|
||||
unsigned wind_direction_raw = bds_bits(msg, 15, 23);
|
||||
unsigned temperature_sign = bds_bit(msg, 24);
|
||||
unsigned static_air_temperature_raw = bds_bits(msg, 25, 34);
|
||||
unsigned pressure_valid = bds_bit(msg, 35);
|
||||
unsigned static_pressure_raw = bds_bits(msg, 36, 46);
|
||||
unsigned turbulence_valid = bds_bit(msg, 47);
|
||||
unsigned turbulence_raw = bds_bits(msg, 48, 49);
|
||||
unsigned humidity_valid = bds_bit(msg, 50);
|
||||
unsigned humidity_raw = bds_bits(msg, 51, 56);
|
||||
int score = 0;
|
||||
if (source <= 6) {
|
||||
score += 4;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
if (wind_valid) {
|
||||
if (wind_speed_raw <= 511) {
|
||||
score += 9;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
double wind_direction = wind_direction_raw * 180.0 / 256.0;
|
||||
if (wind_direction >= 0 && wind_direction <= 360) {
|
||||
score += 9;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::array<std::string, 7> allbds = {
|
||||
"10", "17", "20", "30",
|
||||
"40", "50", "60"
|
||||
};
|
||||
bool mask[] = {IS10, IS17, IS20, IS30, IS40, IS50, IS60};
|
||||
for (size_t i = 0; i < 7; ++i) {
|
||||
if (mask[i]) {
|
||||
bds_result.push_back(allbds[i]);
|
||||
}
|
||||
score += 2;
|
||||
}
|
||||
double temperature = temperature_sign ? (static_air_temperature_raw - pow(2, 10)) * 0.25 : static_air_temperature_raw * 0.25;
|
||||
if (temperature >= -128 && temperature <= 128) {
|
||||
score += 10;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
if (pressure_valid) {
|
||||
if (static_pressure_raw <= 2048) {
|
||||
score += 11;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return bds_result;
|
||||
else {
|
||||
score += 1;
|
||||
}
|
||||
if (turbulence_valid) {
|
||||
if (turbulence_raw <= 3) {
|
||||
score += 2;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
score += 1;
|
||||
}
|
||||
if (humidity_valid) {
|
||||
double humidity = humidity_raw * (100.0 / 64);
|
||||
if (humidity >= 0 && humidity <= 100) {
|
||||
score += 6;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
score += 1;
|
||||
}
|
||||
return score;
|
||||
}
|
||||
// std::vector<std::string> infer2(const std::string& msg, bool mrar) {
|
||||
// auto df = SSR::decode_df(msg);
|
||||
// if (allzeros(msg)) {
|
||||
// return {};
|
||||
// }
|
||||
// if (df == Downlink_Format::Extended_Squitter_17) {
|
||||
// auto tc = type_code(msg);
|
||||
// if (!tc) {
|
||||
// return {};
|
||||
// }
|
||||
// if (tc >= 1 && tc <= 4) return {"08"}; // identification and category
|
||||
// if (tc >= 5 && tc <= 8) return {"06"}; // surface movement
|
||||
// if (tc >= 9 && tc <= 18) return {"05"}; // airborne position, baro-alt
|
||||
// if (tc == 19) return {"09"}; // airborne velocity
|
||||
// if (tc >= 20 && tc <= 22) return {"05"}; // airborne position, gnss-alt
|
||||
// if (tc == 28) return {"61"}; // aircraft status
|
||||
// if (tc == 29) return {"62"}; // target state and status
|
||||
// if (tc == 31) return {"65"}; // operational status
|
||||
// }
|
||||
// if (df != Downlink_Format::Comm_B_Altitude_Reply_20 && df != Downlink_Format::Comm_B_Identity_Reply_21) {
|
||||
// static Frequency_Limit mt;
|
||||
// if (mt.test()) {
|
||||
// std::cout << std::format("非20 21 异常舍弃 hex: {} bin:{} \n", bin2hex(msg), msg);
|
||||
// }
|
||||
// return {};
|
||||
// }
|
||||
// // if (bin2<int>(msg.substr(8, 5)) != 0 || bin2<int>(msg.substr(13, 6)) != 0) {
|
||||
// // static Frequency_Limit mt;
|
||||
// // // if (mt.test()) {
|
||||
// // std::cout << std::format("异常舍弃 hex: {} bin:{} \n", bin2hex(msg), msg);
|
||||
// // // }
|
||||
// // return {};
|
||||
// // }
|
||||
// std::string data = databin(msg);
|
||||
// if (allzeros(data)) {
|
||||
// static Frequency_Limit mt;
|
||||
// if (mt.test()) {
|
||||
// std::cout << std::format("bds解码出了allzeros hex: {} bin:{} \n", bin2hex(msg), msg);
|
||||
// }
|
||||
// return {};
|
||||
// }
|
||||
// struct Candidate {
|
||||
// const char *name;
|
||||
// int (*score)(const std::string&);
|
||||
// };
|
||||
// std::vector<Candidate> candidates = {
|
||||
// {"10", bds10_score},
|
||||
// {"20", bds20_score},
|
||||
// {"30", bds30_score},
|
||||
// {"17", bds17_score},
|
||||
// {"40", bds40_score},
|
||||
// {"50", bds50_score},
|
||||
// {"60", bds60_score}
|
||||
// };
|
||||
// if (true) {
|
||||
// candidates.push_back({"44", bds44_score});
|
||||
// }
|
||||
// int best_score = 0;
|
||||
// const char *best_name = nullptr;
|
||||
// bool ambiguous = false;
|
||||
// for (const auto& candidate : candidates) {
|
||||
// int score = candidate.score(data);
|
||||
// if (score > best_score) {
|
||||
// best_score = score;
|
||||
// best_name = candidate.name;
|
||||
// ambiguous = false;
|
||||
// }
|
||||
// else if (score == best_score && score > 0) {
|
||||
// ambiguous = true;
|
||||
// }
|
||||
// }
|
||||
// if (!best_name || ambiguous) {
|
||||
// static Frequency_Limit mt;
|
||||
// if (mt.test()) {
|
||||
// std::cout << std::format("bds解码出了ambiguous hex: {} bin:{} \n", bin2hex(msg), msg);
|
||||
// }
|
||||
// return {};
|
||||
// }
|
||||
// static Frequency_Limit_Multi mt(0.001);
|
||||
// if (mt.test(best_name)) {
|
||||
// std::cout << std::format("bds解码出了{} \n", best_name);
|
||||
// }
|
||||
// return {best_name};
|
||||
// }
|
||||
std::vector<std::string> infer2(const std::string& msg, bool mrar) {
|
||||
auto df = SSR::decode_df(msg);
|
||||
if (allzeros(msg)) {
|
||||
return {};
|
||||
}
|
||||
// For ADS-B / Mode-S extended squitter
|
||||
if (df == Downlink_Format::Extended_Squitter_17) {
|
||||
auto tc = type_code(msg);
|
||||
if (!tc) {
|
||||
return {};
|
||||
}
|
||||
if (tc >= 1 && tc <= 4) return {"08"}; // identification and category
|
||||
if (tc >= 5 && tc <= 8) return {"06"}; // surface movement
|
||||
if (tc >= 9 && tc <= 18) return {"05"}; // airborne position, baro-alt
|
||||
if (tc == 19) return {"09"}; // airborne velocity
|
||||
if (tc >= 20 && tc <= 22) return {"05"}; // airborne position, gnss-alt
|
||||
if (tc == 28) return {"61"}; // aircraft status
|
||||
if (tc == 29) return {"62"}; // target state and status
|
||||
if (tc == 31) return {"65"}; // operational status
|
||||
}
|
||||
// For Comm-B replies
|
||||
bool IS10 = is10(msg);
|
||||
bool IS17 = is17(msg);
|
||||
bool IS20 = is20(msg);
|
||||
bool IS30 = is30(msg);
|
||||
bool IS40 = is40(msg);
|
||||
bool IS50 = is50(msg);
|
||||
bool IS60 = is60(msg);
|
||||
bool IS44 = is44(msg);
|
||||
bool IS45 = is45(msg);
|
||||
std::vector<std::string> bds_result;
|
||||
if (mrar) {
|
||||
std::array<std::string, 9> allbds = {
|
||||
"10", "17", "20", "30", "40",
|
||||
"44", "45", "50", "60"
|
||||
};
|
||||
bool mask[] = {IS10, IS17, IS20, IS30, IS40, IS44, IS45, IS50, IS60};
|
||||
for (size_t i = 0; i < 9; ++i) {
|
||||
if (mask[i]) {
|
||||
bds_result.push_back(allbds[i]);
|
||||
}
|
||||
if (tc >= 1 && tc <= 4) {
|
||||
return {"08"};
|
||||
}
|
||||
if (tc >= 5 && tc <= 8) {
|
||||
return {"06"};
|
||||
}
|
||||
if (tc >= 9 && tc <= 18) {
|
||||
return {"05"};
|
||||
}
|
||||
if (tc == 19) {
|
||||
return {"09"};
|
||||
}
|
||||
if (tc >= 20 && tc <= 22) {
|
||||
return {"05"};
|
||||
}
|
||||
if (tc == 28) {
|
||||
return {"61"};
|
||||
}
|
||||
if (tc == 29) {
|
||||
return {"62"};
|
||||
}
|
||||
if (tc == 31) {
|
||||
return {"65"};
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::array<std::string, 7> allbds = {
|
||||
"10", "17", "20", "30",
|
||||
"40", "50", "60"
|
||||
};
|
||||
bool mask[] = {IS10, IS17, IS20, IS30, IS40, IS50, IS60};
|
||||
for (size_t i = 0; i < 7; ++i) {
|
||||
if (mask[i]) {
|
||||
bds_result.push_back(allbds[i]);
|
||||
}
|
||||
if (df != Downlink_Format::Comm_B_Altitude_Reply_20 && df != Downlink_Format::Comm_B_Identity_Reply_21) {
|
||||
static Frequency_Limit mt;
|
||||
if (mt.test()) {
|
||||
std::cout << std::format("非20 21 异常舍弃 hex: {} bin:{} df{}\n", bin2hex(msg), msg, Psc::to_string(df));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
if (bin2<int>(msg.substr(8, 5)) != 0 || bin2<int>(msg.substr(13, 6)) != 0) {
|
||||
static Frequency_Limit mt;
|
||||
if (mt.test()) {
|
||||
std::cout << std::format("原因是 DR/UM 非 0 时,这条 DF20/DF21 下行应答里带了额外的通信控制状态 {} \n", msg);
|
||||
}
|
||||
}
|
||||
return bds_result;
|
||||
std::string data = databin(msg);
|
||||
if (allzeros(data)) {
|
||||
static Frequency_Limit mt;
|
||||
if (mt.test()) {
|
||||
std::cout << std::format("bds解码出了allzeros hex: {} bin:{}\n", bin2hex(msg), msg);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
struct Candidate {
|
||||
const char *name;
|
||||
int (*score)(const std::string&);
|
||||
};
|
||||
std::vector<Candidate> candidates = {
|
||||
{"10", bds10_score},
|
||||
{"20", bds20_score},
|
||||
{"30", bds30_score},
|
||||
{"17", bds17_score},
|
||||
{"40", bds40_score},
|
||||
{"50", bds50_score},
|
||||
{"60", bds60_score}
|
||||
};
|
||||
if (true) {
|
||||
candidates.push_back({"44", bds44_score});
|
||||
}
|
||||
int best_score = 0;
|
||||
const char *best_name = nullptr;
|
||||
std::vector<const char*> best_names;
|
||||
for (const auto& candidate : candidates) {
|
||||
int score = candidate.score(data);
|
||||
if (score > best_score) {
|
||||
best_score = score;
|
||||
best_name = candidate.name;
|
||||
best_names.clear();
|
||||
best_names.emplace_back(candidate.name);
|
||||
}
|
||||
else if (score == best_score && score > 0) {
|
||||
best_names.emplace_back(candidate.name);
|
||||
}
|
||||
}
|
||||
if (!best_name || best_names.size() > 1) {
|
||||
static Frequency_Limit mt;
|
||||
if (mt.test()) {
|
||||
std::ostringstream oss;
|
||||
for (auto name : best_names) {
|
||||
if (oss.tellp() > 0) {
|
||||
oss << ",";
|
||||
}
|
||||
oss << name;
|
||||
}
|
||||
std::cout << std::format("bds解码出了ambiguous score:{} best:[{}] hex:{} bin:{}\n", best_score, oss.str(), bin2hex(msg), msg);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
static Frequency_Limit_Multi mt(0.001);
|
||||
if (mt.test(best_name)) {
|
||||
std::cout << std::format("bds解码出了{} score:{}\n", best_name, best_score);
|
||||
}
|
||||
return {best_name};
|
||||
}
|
||||
}
|
||||
#ifdef _USE_GTEST
|
||||
#include <gtest/gtest.h>
|
||||
#endif
|
||||
|
||||
|
||||
+3
-4
@@ -9,8 +9,7 @@ _attach_source_dir("SSR" "${CMAKE_CURRENT_LIST_DIR}/test")
|
||||
_depend(SSR ${Core})
|
||||
|
||||
|
||||
|
||||
_create(dll readsb2)
|
||||
_attach_include_dir(readsb2 "${CMAKE_CURRENT_LIST_DIR}")
|
||||
_attach_source_dir(readsb2 "${CMAKE_CURRENT_LIST_DIR}/readsb2")
|
||||
#_create(dll readsb2)
|
||||
#_attach_include_dir(readsb2 "${CMAKE_CURRENT_LIST_DIR}")
|
||||
#_attach_source_dir(readsb2 "${CMAKE_CURRENT_LIST_DIR}/readsb2")
|
||||
|
||||
|
||||
@@ -27,7 +27,13 @@ TEST_F(BdsTest, TestBdsInfer) {
|
||||
|
||||
// std::cout << infer("A0001838201584F23468207CDFA5").value();
|
||||
}
|
||||
|
||||
TEST_F(BdsTest, Infer2LargeBds17ReservedBitsDoesNotThrow) {
|
||||
std::string msg = "10100000000000000000000000000000";
|
||||
msg += "00010000000000110000101010000000111101010000000000000000";
|
||||
msg += "000000000000000000000000";
|
||||
EXPECT_NO_THROW(infer2(msg, true));
|
||||
EXPECT_NO_THROW(infer2("1010000000000000000011110011100100010000000000110000101010000000111101010000000000000000001110000101001101010111", true));
|
||||
}
|
||||
TEST_F(BdsTest, TestBdsIs50Or60) {
|
||||
auto result = is50or60(hex2bin("A0001838201584F23468207CDFA5"), 0, 0, 0);
|
||||
EXPECT_EQ(result, ""); // Check if the optional is empty
|
||||
|
||||
Reference in New Issue
Block a user