mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 08:50:05 +00:00
Parse Volume Coverage Pattern Data (Message Type 5)
This commit is contained in:
parent
2fc12d44db
commit
517c77cb5f
7 changed files with 635 additions and 52 deletions
|
|
@ -92,6 +92,9 @@ public:
|
|||
|
||||
virtual bool Parse(std::istream& is) = 0;
|
||||
|
||||
static constexpr double ANGLE_DATA_SCALE = 0.005493125;
|
||||
static constexpr double AZ_EL_RATE_DATA_SCALE = 0.001373291015625;
|
||||
|
||||
private:
|
||||
std::unique_ptr<MessageImpl> p;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/wsr88d/rda/message.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace wsr88d
|
||||
{
|
||||
namespace rda
|
||||
{
|
||||
|
||||
class VolumeCoveragePatternDataImpl;
|
||||
|
||||
class VolumeCoveragePatternData : public Message
|
||||
{
|
||||
public:
|
||||
explicit VolumeCoveragePatternData();
|
||||
~VolumeCoveragePatternData();
|
||||
|
||||
VolumeCoveragePatternData(const Message&) = delete;
|
||||
VolumeCoveragePatternData&
|
||||
operator=(const VolumeCoveragePatternData&) = delete;
|
||||
|
||||
VolumeCoveragePatternData(VolumeCoveragePatternData&&) noexcept;
|
||||
VolumeCoveragePatternData& operator=(VolumeCoveragePatternData&&) noexcept;
|
||||
|
||||
uint16_t pattern_type() const;
|
||||
uint16_t pattern_number() const;
|
||||
uint16_t number_of_elevation_cuts() const;
|
||||
uint8_t version() const;
|
||||
uint8_t clutter_map_group_number() const;
|
||||
float doppler_velocity_resolution() const;
|
||||
uint8_t pulse_width() const;
|
||||
uint16_t vcp_sequencing() const;
|
||||
uint16_t number_of_elevations() const;
|
||||
uint16_t maximum_sails_cuts() const;
|
||||
bool sequence_active() const;
|
||||
bool truncated_vcp() const;
|
||||
uint16_t vcp_supplemental_data() const;
|
||||
bool sails_vcp() const;
|
||||
uint16_t number_of_sails_cuts() const;
|
||||
bool mrle_vcp() const;
|
||||
uint16_t number_of_mrle_cuts() const;
|
||||
bool mpda_vcp() const;
|
||||
bool base_tilt_vcp() const;
|
||||
uint16_t number_of_base_tilts() const;
|
||||
double elevation_angle(uint16_t e) const;
|
||||
uint8_t channel_configuration(uint16_t e) const;
|
||||
uint8_t waveform_type(uint16_t e) const;
|
||||
uint8_t super_resolution_control(uint16_t e) const;
|
||||
bool half_degree_azimuth(uint16_t e) const;
|
||||
bool quarter_km_reflectivity(uint16_t e) const;
|
||||
bool doppler_to_300km(uint16_t e) const;
|
||||
bool dual_polarization_to_300km(uint16_t e) const;
|
||||
uint8_t surveillance_prf_number(uint16_t e) const;
|
||||
uint16_t surveillance_prf_pulse_count_radial(uint16_t e) const;
|
||||
double azimuth_rate(uint16_t e) const;
|
||||
float reflectivity_threshold(uint16_t e) const;
|
||||
float velocity_threshold(uint16_t e) const;
|
||||
float spectrum_width_threshold(uint16_t e) const;
|
||||
float differential_reflectivity_threshold(uint16_t e) const;
|
||||
float differential_phase_threshold(uint16_t e) const;
|
||||
float correlation_coefficient_threshold(uint16_t e) const;
|
||||
uint16_t supplemental_data(uint16_t e) const;
|
||||
bool sails_cut(uint16_t e) const;
|
||||
uint16_t sails_sequence_number(uint16_t e) const;
|
||||
bool mrle_cut(uint16_t e) const;
|
||||
uint16_t mrle_sequence_number(uint16_t e) const;
|
||||
bool mpda_cut(uint16_t e) const;
|
||||
bool base_tilt_cut(uint16_t e) const;
|
||||
double ebc_angle(uint16_t e) const;
|
||||
double edge_angle(uint16_t e, uint16_t s) const;
|
||||
uint16_t doppler_prf_number(uint16_t e, uint16_t s) const;
|
||||
uint16_t doppler_prf_pulse_count_radial(uint16_t e, uint16_t s) const;
|
||||
|
||||
bool Parse(std::istream& is);
|
||||
|
||||
static std::unique_ptr<VolumeCoveragePatternData>
|
||||
Create(MessageHeader&& header, std::istream& is);
|
||||
|
||||
private:
|
||||
std::unique_ptr<VolumeCoveragePatternDataImpl> p;
|
||||
};
|
||||
|
||||
} // namespace rda
|
||||
} // namespace wsr88d
|
||||
} // namespace scwx
|
||||
|
|
@ -91,32 +91,24 @@ bool ClutterFilterMap::Parse(std::istream& is)
|
|||
p->mapGenerationTime_ = htons(p->mapGenerationTime_);
|
||||
numElevationSegments = htons(numElevationSegments);
|
||||
|
||||
if (is.eof())
|
||||
if (p->mapGenerationDate_ < 1)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Reached end of file (1)";
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Invalid date: " << p->mapGenerationDate_;
|
||||
messageValid = false;
|
||||
}
|
||||
else
|
||||
if (p->mapGenerationTime_ > 1440)
|
||||
{
|
||||
if (p->mapGenerationDate_ < 1)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Invalid date: " << p->mapGenerationDate_;
|
||||
messageValid = false;
|
||||
}
|
||||
if (p->mapGenerationTime_ > 1440)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Invalid time: " << p->mapGenerationTime_;
|
||||
messageValid = false;
|
||||
}
|
||||
if (numElevationSegments < 1 || numElevationSegments > 5)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_
|
||||
<< "Invalid number of elevation segments: " << numElevationSegments;
|
||||
messageValid = false;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Invalid time: " << p->mapGenerationTime_;
|
||||
messageValid = false;
|
||||
}
|
||||
if (numElevationSegments < 1 || numElevationSegments > 5)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_
|
||||
<< "Invalid number of elevation segments: " << numElevationSegments;
|
||||
messageValid = false;
|
||||
}
|
||||
|
||||
if (!messageValid)
|
||||
|
|
@ -138,22 +130,13 @@ bool ClutterFilterMap::Parse(std::istream& is)
|
|||
|
||||
numRangeZones = htons(numRangeZones);
|
||||
|
||||
if (is.eof())
|
||||
if (numRangeZones < 1 || numRangeZones > 20)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Reached end of file (2)";
|
||||
<< logPrefix_
|
||||
<< "Invalid number of range zones: " << numRangeZones;
|
||||
messageValid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numRangeZones < 1 || numRangeZones > 20)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_
|
||||
<< "Invalid number of range zones: " << numRangeZones;
|
||||
messageValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!messageValid)
|
||||
{
|
||||
|
|
@ -173,26 +156,17 @@ bool ClutterFilterMap::Parse(std::istream& is)
|
|||
zone.opCode = htons(zone.opCode);
|
||||
zone.endRange = htons(zone.endRange);
|
||||
|
||||
if (is.eof())
|
||||
if (zone.opCode > 2)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Reached end of file (3)";
|
||||
<< logPrefix_ << "Invalid op code: " << zone.opCode;
|
||||
messageValid = false;
|
||||
}
|
||||
else
|
||||
if (zone.endRange > 511)
|
||||
{
|
||||
if (zone.opCode > 2)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Invalid op code: " << zone.opCode;
|
||||
messageValid = false;
|
||||
}
|
||||
if (zone.endRange > 511)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Invalid end range: " << zone.endRange;
|
||||
messageValid = false;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Invalid end range: " << zone.endRange;
|
||||
messageValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ bool Message::ValidateMessage(std::istream& is, size_t bytesRead) const
|
|||
|
||||
if (is.eof())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Reached end of file";
|
||||
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Reached end of data stream";
|
||||
messageValid = false;
|
||||
}
|
||||
else if (is.fail())
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <scwx/wsr88d/rda/clutter_filter_map.hpp>
|
||||
#include <scwx/wsr88d/rda/performance_maintenance_data.hpp>
|
||||
#include <scwx/wsr88d/rda/rda_adaptation_data.hpp>
|
||||
#include <scwx/wsr88d/rda/volume_coverage_pattern_data.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
|
@ -24,6 +25,7 @@ typedef std::function<std::unique_ptr<Message>(MessageHeader&&, std::istream&)>
|
|||
|
||||
static const std::unordered_map<uint8_t, CreateMessageFunction> create_ {
|
||||
{3, PerformanceMaintenanceData::Create},
|
||||
{5, VolumeCoveragePatternData::Create},
|
||||
{15, ClutterFilterMap::Create},
|
||||
{18, RdaAdaptationData::Create}};
|
||||
|
||||
|
|
|
|||
513
wxdata/source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp
Normal file
513
wxdata/source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp
Normal file
|
|
@ -0,0 +1,513 @@
|
|||
#include <scwx/wsr88d/rda/volume_coverage_pattern_data.hpp>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace wsr88d
|
||||
{
|
||||
namespace rda
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ =
|
||||
"[scwx::wsr88d::rda::volume_coverage_pattern_data] ";
|
||||
|
||||
struct Sector;
|
||||
|
||||
static void ReadSector(std::istream& is, Sector& s);
|
||||
static void SwapSector(Sector& s);
|
||||
|
||||
struct Sector
|
||||
{
|
||||
uint16_t edgeAngle_;
|
||||
uint16_t dopplerPrfNumber_;
|
||||
uint16_t dopplerPrfPulseCountRadial_;
|
||||
|
||||
Sector() :
|
||||
edgeAngle_ {0}, dopplerPrfNumber_ {0}, dopplerPrfPulseCountRadial_ {0}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct ElevationCut
|
||||
{
|
||||
uint16_t elevationAngle_;
|
||||
uint8_t channelConfiguration_;
|
||||
uint8_t waveformType_;
|
||||
uint8_t superResolutionControl_;
|
||||
uint8_t surveillancePrfNumber_;
|
||||
uint16_t surveillancePrfPulseCountRadial_;
|
||||
int16_t azimuthRate_;
|
||||
uint16_t reflectivityThreshold_;
|
||||
uint16_t velocityThreshold_;
|
||||
uint16_t spectrumWidthThreshold_;
|
||||
uint16_t differentialReflectivityThreshold_;
|
||||
uint16_t differentialPhaseThreshold_;
|
||||
uint16_t correlationCoefficientThreshold_;
|
||||
std::array<Sector, 3> sector_;
|
||||
uint16_t supplementalData_;
|
||||
uint16_t ebcAngle_;
|
||||
|
||||
ElevationCut() :
|
||||
elevationAngle_ {0},
|
||||
channelConfiguration_ {0},
|
||||
waveformType_ {0},
|
||||
superResolutionControl_ {0},
|
||||
surveillancePrfNumber_ {0},
|
||||
surveillancePrfPulseCountRadial_ {0},
|
||||
azimuthRate_ {0},
|
||||
reflectivityThreshold_ {0},
|
||||
velocityThreshold_ {0},
|
||||
spectrumWidthThreshold_ {0},
|
||||
differentialReflectivityThreshold_ {0},
|
||||
differentialPhaseThreshold_ {0},
|
||||
correlationCoefficientThreshold_ {0},
|
||||
sector_(),
|
||||
supplementalData_ {0},
|
||||
ebcAngle_ {0}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class VolumeCoveragePatternDataImpl
|
||||
{
|
||||
public:
|
||||
explicit VolumeCoveragePatternDataImpl() :
|
||||
patternType_ {0},
|
||||
patternNumber_ {0},
|
||||
version_ {0},
|
||||
clutterMapGroupNumber_ {0},
|
||||
dopplerVelocityResolution_ {0},
|
||||
pulseWidth_ {0},
|
||||
vcpSequencing_ {0},
|
||||
vcpSupplementalData_ {0},
|
||||
elevationCuts_() {};
|
||||
~VolumeCoveragePatternDataImpl() = default;
|
||||
|
||||
uint16_t patternType_;
|
||||
uint16_t patternNumber_;
|
||||
uint8_t version_;
|
||||
uint8_t clutterMapGroupNumber_;
|
||||
uint8_t dopplerVelocityResolution_;
|
||||
uint8_t pulseWidth_;
|
||||
uint16_t vcpSequencing_;
|
||||
uint16_t vcpSupplementalData_;
|
||||
std::vector<ElevationCut> elevationCuts_;
|
||||
};
|
||||
|
||||
VolumeCoveragePatternData::VolumeCoveragePatternData() :
|
||||
Message(), p(std::make_unique<VolumeCoveragePatternDataImpl>())
|
||||
{
|
||||
}
|
||||
VolumeCoveragePatternData::~VolumeCoveragePatternData() = default;
|
||||
|
||||
VolumeCoveragePatternData::VolumeCoveragePatternData(
|
||||
VolumeCoveragePatternData&&) noexcept = default;
|
||||
VolumeCoveragePatternData& VolumeCoveragePatternData::operator=(
|
||||
VolumeCoveragePatternData&&) noexcept = default;
|
||||
|
||||
uint16_t VolumeCoveragePatternData::pattern_type() const
|
||||
{
|
||||
return p->patternType_;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::pattern_number() const
|
||||
{
|
||||
return p->patternNumber_;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::number_of_elevation_cuts() const
|
||||
{
|
||||
return static_cast<uint16_t>(p->elevationCuts_.size());
|
||||
}
|
||||
|
||||
uint8_t VolumeCoveragePatternData::version() const
|
||||
{
|
||||
return p->version_;
|
||||
}
|
||||
|
||||
uint8_t VolumeCoveragePatternData::clutter_map_group_number() const
|
||||
{
|
||||
return p->clutterMapGroupNumber_;
|
||||
}
|
||||
|
||||
float VolumeCoveragePatternData::doppler_velocity_resolution() const
|
||||
{
|
||||
float resolution = 0.0f;
|
||||
|
||||
switch (p->dopplerVelocityResolution_)
|
||||
{
|
||||
case 2: resolution = 0.5f; break;
|
||||
case 4: resolution = 1.0f; break;
|
||||
}
|
||||
|
||||
return resolution;
|
||||
}
|
||||
|
||||
uint8_t VolumeCoveragePatternData::pulse_width() const
|
||||
{
|
||||
return p->pulseWidth_;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::vcp_sequencing() const
|
||||
{
|
||||
return p->vcpSequencing_;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::number_of_elevations() const
|
||||
{
|
||||
return p->vcpSequencing_ & 0x001f;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::maximum_sails_cuts() const
|
||||
{
|
||||
return (p->vcpSequencing_ & 0x0060) >> 5;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::sequence_active() const
|
||||
{
|
||||
return p->vcpSequencing_ & 0x2000;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::truncated_vcp() const
|
||||
{
|
||||
return p->vcpSequencing_ & 0x4000;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::vcp_supplemental_data() const
|
||||
{
|
||||
return p->vcpSupplementalData_;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::sails_vcp() const
|
||||
{
|
||||
return p->vcpSupplementalData_ & 0x0001;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::number_of_sails_cuts() const
|
||||
{
|
||||
return (p->vcpSupplementalData_ & 0x000E) >> 1;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::mrle_vcp() const
|
||||
{
|
||||
return p->vcpSupplementalData_ & 0x0010;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::number_of_mrle_cuts() const
|
||||
{
|
||||
return (p->vcpSupplementalData_ & 0x00E0) >> 5;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::mpda_vcp() const
|
||||
{
|
||||
return p->vcpSupplementalData_ & 0x0800;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::base_tilt_vcp() const
|
||||
{
|
||||
return p->vcpSupplementalData_ & 0x1000;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::number_of_base_tilts() const
|
||||
{
|
||||
return (p->vcpSupplementalData_ & 0xE000) >> 13;
|
||||
}
|
||||
|
||||
double VolumeCoveragePatternData::elevation_angle(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].elevationAngle_ * ANGLE_DATA_SCALE;
|
||||
}
|
||||
|
||||
uint8_t VolumeCoveragePatternData::channel_configuration(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].channelConfiguration_;
|
||||
}
|
||||
|
||||
uint8_t VolumeCoveragePatternData::waveform_type(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].waveformType_;
|
||||
}
|
||||
|
||||
uint8_t VolumeCoveragePatternData::super_resolution_control(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].superResolutionControl_;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::half_degree_azimuth(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].superResolutionControl_ & 0x0001;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::quarter_km_reflectivity(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].superResolutionControl_ & 0x0002;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::doppler_to_300km(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].superResolutionControl_ & 0x0004;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::dual_polarization_to_300km(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].superResolutionControl_ & 0x0008;
|
||||
}
|
||||
|
||||
uint8_t VolumeCoveragePatternData::surveillance_prf_number(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].surveillancePrfNumber_;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
VolumeCoveragePatternData::surveillance_prf_pulse_count_radial(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].surveillancePrfPulseCountRadial_;
|
||||
}
|
||||
|
||||
double VolumeCoveragePatternData::azimuth_rate(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].azimuthRate_ * AZ_EL_RATE_DATA_SCALE;
|
||||
}
|
||||
|
||||
float VolumeCoveragePatternData::reflectivity_threshold(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].reflectivityThreshold_ * 0.125f;
|
||||
}
|
||||
|
||||
float VolumeCoveragePatternData::velocity_threshold(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].velocityThreshold_ * 0.125f;
|
||||
}
|
||||
|
||||
float VolumeCoveragePatternData::spectrum_width_threshold(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].spectrumWidthThreshold_ * 0.125f;
|
||||
}
|
||||
|
||||
float VolumeCoveragePatternData::differential_reflectivity_threshold(
|
||||
uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].differentialReflectivityThreshold_ * 0.125f;
|
||||
}
|
||||
|
||||
float VolumeCoveragePatternData::differential_phase_threshold(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].differentialPhaseThreshold_ * 0.125f;
|
||||
}
|
||||
|
||||
float VolumeCoveragePatternData::correlation_coefficient_threshold(
|
||||
uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].correlationCoefficientThreshold_ * 0.125f;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::supplemental_data(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].supplementalData_;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::sails_cut(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].supplementalData_ & 0x0001;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::sails_sequence_number(uint16_t e) const
|
||||
{
|
||||
return (p->elevationCuts_[e].supplementalData_ & 0x000E) >> 1;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::mrle_cut(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].supplementalData_ & 0x0010;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::mrle_sequence_number(uint16_t e) const
|
||||
{
|
||||
return (p->elevationCuts_[e].supplementalData_ & 0x00E0) >> 5;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::mpda_cut(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].supplementalData_ & 0x0200;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::base_tilt_cut(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].supplementalData_ & 0x0400;
|
||||
}
|
||||
|
||||
double VolumeCoveragePatternData::ebc_angle(uint16_t e) const
|
||||
{
|
||||
return p->elevationCuts_[e].ebcAngle_ * ANGLE_DATA_SCALE;
|
||||
}
|
||||
|
||||
double VolumeCoveragePatternData::edge_angle(uint16_t e, uint16_t s) const
|
||||
{
|
||||
return p->elevationCuts_[e].sector_[s].edgeAngle_ * ANGLE_DATA_SCALE;
|
||||
}
|
||||
|
||||
uint16_t VolumeCoveragePatternData::doppler_prf_number(uint16_t e,
|
||||
uint16_t s) const
|
||||
{
|
||||
return p->elevationCuts_[e].sector_[s].dopplerPrfNumber_;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
VolumeCoveragePatternData::doppler_prf_pulse_count_radial(uint16_t e,
|
||||
uint16_t s) const
|
||||
{
|
||||
return p->elevationCuts_[e].sector_[s].dopplerPrfPulseCountRadial_;
|
||||
}
|
||||
|
||||
bool VolumeCoveragePatternData::Parse(std::istream& is)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Parsing Volume Coverage Pattern Data (Message Type 5)";
|
||||
|
||||
bool messageValid = true;
|
||||
size_t bytesRead = 0;
|
||||
|
||||
uint16_t messageSize = 0;
|
||||
uint16_t numberOfElevationCuts = 0;
|
||||
|
||||
is.read(reinterpret_cast<char*>(&messageSize), 2); // 1
|
||||
is.read(reinterpret_cast<char*>(&p->patternType_), 2); // 2
|
||||
is.read(reinterpret_cast<char*>(&p->patternNumber_), 2); // 3
|
||||
is.read(reinterpret_cast<char*>(&numberOfElevationCuts), 2); // 4
|
||||
is.read(reinterpret_cast<char*>(&p->version_), 1); // 5
|
||||
is.read(reinterpret_cast<char*>(&p->clutterMapGroupNumber_), 1); // 5
|
||||
is.read(reinterpret_cast<char*>(&p->dopplerVelocityResolution_), 1); // 6
|
||||
is.read(reinterpret_cast<char*>(&p->pulseWidth_), 1); // 6
|
||||
is.seekg(4, std::ios_base::cur); // 7-8
|
||||
is.read(reinterpret_cast<char*>(&p->vcpSequencing_), 2); // 9
|
||||
is.read(reinterpret_cast<char*>(&p->vcpSupplementalData_), 2); // 10
|
||||
is.seekg(2, std::ios_base::cur); // 11
|
||||
bytesRead += 22;
|
||||
|
||||
messageSize = htons(messageSize);
|
||||
p->patternType_ = htons(p->patternType_);
|
||||
p->patternNumber_ = htons(p->patternNumber_);
|
||||
numberOfElevationCuts = htons(numberOfElevationCuts);
|
||||
p->vcpSequencing_ = htons(p->vcpSequencing_);
|
||||
p->vcpSupplementalData_ = htons(p->vcpSupplementalData_);
|
||||
|
||||
if (messageSize < 34 || messageSize > 747)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Invalid message size: " << messageSize;
|
||||
messageValid = false;
|
||||
}
|
||||
if (numberOfElevationCuts < 1 || numberOfElevationCuts > 32)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_
|
||||
<< "Invalid number of elevation cuts: " << numberOfElevationCuts;
|
||||
messageValid = false;
|
||||
}
|
||||
|
||||
if (!messageValid)
|
||||
{
|
||||
numberOfElevationCuts = 0;
|
||||
}
|
||||
|
||||
p->elevationCuts_.resize(numberOfElevationCuts);
|
||||
|
||||
for (uint16_t e = 0; e < numberOfElevationCuts; ++e)
|
||||
{
|
||||
ElevationCut& c = p->elevationCuts_[e];
|
||||
|
||||
is.read(reinterpret_cast<char*>(&c.elevationAngle_), 2); // E1
|
||||
is.read(reinterpret_cast<char*>(&c.channelConfiguration_), 1); // E2
|
||||
is.read(reinterpret_cast<char*>(&c.waveformType_), 1); // E2
|
||||
is.read(reinterpret_cast<char*>(&c.superResolutionControl_), 1); // E3
|
||||
is.read(reinterpret_cast<char*>(&c.surveillancePrfNumber_), 1); // E3
|
||||
is.read(reinterpret_cast<char*>(&c.surveillancePrfPulseCountRadial_),
|
||||
2); // E4
|
||||
is.read(reinterpret_cast<char*>(&c.azimuthRate_), 2); // E5
|
||||
is.read(reinterpret_cast<char*>(&c.reflectivityThreshold_), 2); // E6
|
||||
is.read(reinterpret_cast<char*>(&c.velocityThreshold_), 2); // E7
|
||||
is.read(reinterpret_cast<char*>(&c.spectrumWidthThreshold_), 2); // E8
|
||||
is.read(reinterpret_cast<char*>(&c.differentialReflectivityThreshold_),
|
||||
2); // E9
|
||||
is.read(reinterpret_cast<char*>(&c.differentialPhaseThreshold_),
|
||||
2); // E10
|
||||
is.read(reinterpret_cast<char*>(&c.correlationCoefficientThreshold_),
|
||||
2); // E11
|
||||
ReadSector(is, c.sector_[0]); // E12-E14
|
||||
is.read(reinterpret_cast<char*>(&c.supplementalData_), 2); // E15
|
||||
ReadSector(is, c.sector_[1]); // E16-E18
|
||||
is.read(reinterpret_cast<char*>(&c.ebcAngle_), 2); // E19
|
||||
ReadSector(is, c.sector_[2]); // E20-E22
|
||||
is.seekg(2, std::ios_base::cur); // E23
|
||||
bytesRead += 46;
|
||||
|
||||
c.elevationAngle_ = htons(c.elevationAngle_);
|
||||
c.surveillancePrfPulseCountRadial_ =
|
||||
htons(c.surveillancePrfPulseCountRadial_);
|
||||
c.azimuthRate_ = htons(c.azimuthRate_);
|
||||
c.reflectivityThreshold_ = htons(c.reflectivityThreshold_);
|
||||
c.velocityThreshold_ = htons(c.velocityThreshold_);
|
||||
c.spectrumWidthThreshold_ = htons(c.spectrumWidthThreshold_);
|
||||
c.differentialReflectivityThreshold_ =
|
||||
htons(c.differentialReflectivityThreshold_);
|
||||
c.differentialPhaseThreshold_ = htons(c.differentialPhaseThreshold_);
|
||||
c.correlationCoefficientThreshold_ =
|
||||
htons(c.correlationCoefficientThreshold_);
|
||||
c.supplementalData_ = htons(c.supplementalData_);
|
||||
c.ebcAngle_ = htons(c.ebcAngle_);
|
||||
|
||||
for (size_t s = 0; s < c.sector_.size(); s++)
|
||||
{
|
||||
SwapSector(c.sector_[s]);
|
||||
}
|
||||
}
|
||||
|
||||
if (messageValid && bytesRead != messageSize * 2)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Bytes read (" << bytesRead
|
||||
<< ") not equal to message size (" << messageSize * 2 << ")";
|
||||
}
|
||||
|
||||
if (!ValidateMessage(is, bytesRead))
|
||||
{
|
||||
messageValid = false;
|
||||
}
|
||||
|
||||
if (!messageValid)
|
||||
{
|
||||
p->elevationCuts_.resize(0);
|
||||
p->elevationCuts_.shrink_to_fit();
|
||||
}
|
||||
|
||||
return messageValid;
|
||||
}
|
||||
|
||||
std::unique_ptr<VolumeCoveragePatternData>
|
||||
VolumeCoveragePatternData::Create(MessageHeader&& header, std::istream& is)
|
||||
{
|
||||
std::unique_ptr<VolumeCoveragePatternData> message =
|
||||
std::make_unique<VolumeCoveragePatternData>();
|
||||
message->set_header(std::move(header));
|
||||
message->Parse(is);
|
||||
return message;
|
||||
}
|
||||
|
||||
static void ReadSector(std::istream& is, Sector& s)
|
||||
{
|
||||
is.read(reinterpret_cast<char*>(&s.edgeAngle_), 2); // S1
|
||||
is.read(reinterpret_cast<char*>(&s.dopplerPrfNumber_), 2); // S2
|
||||
is.read(reinterpret_cast<char*>(&s.dopplerPrfPulseCountRadial_), 2); // S3
|
||||
}
|
||||
|
||||
static void SwapSector(Sector& s)
|
||||
{
|
||||
s.edgeAngle_ = htons(s.edgeAngle_);
|
||||
s.dopplerPrfNumber_ = htons(s.dopplerPrfNumber_);
|
||||
s.dopplerPrfPulseCountRadial_ = htons(s.dopplerPrfPulseCountRadial_);
|
||||
}
|
||||
|
||||
} // namespace rda
|
||||
} // namespace wsr88d
|
||||
} // namespace scwx
|
||||
|
|
@ -13,13 +13,15 @@ set(HDR_WSR88D_RDA include/scwx/wsr88d/rda/clutter_filter_map.hpp
|
|||
include/scwx/wsr88d/rda/message_factory.hpp
|
||||
include/scwx/wsr88d/rda/message_header.hpp
|
||||
include/scwx/wsr88d/rda/performance_maintenance_data.hpp
|
||||
include/scwx/wsr88d/rda/rda_adaptation_data.hpp)
|
||||
include/scwx/wsr88d/rda/rda_adaptation_data.hpp
|
||||
include/scwx/wsr88d/rda/volume_coverage_pattern_data.hpp)
|
||||
set(SRC_WSR88D_RDA source/scwx/wsr88d/rda/clutter_filter_map.cpp
|
||||
source/scwx/wsr88d/rda/message.cpp
|
||||
source/scwx/wsr88d/rda/message_factory.cpp
|
||||
source/scwx/wsr88d/rda/message_header.cpp
|
||||
source/scwx/wsr88d/rda/performance_maintenance_data.cpp
|
||||
source/scwx/wsr88d/rda/rda_adaptation_data.cpp)
|
||||
source/scwx/wsr88d/rda/rda_adaptation_data.cpp
|
||||
source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp)
|
||||
|
||||
add_library(wxdata OBJECT ${HDR_UTIL}
|
||||
${SRC_UTIL}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue