From 4d933ae8172e2506bd1b8a88e56e76a16906c0bb Mon Sep 17 00:00:00 2001 From: Hannah DeFazio Date: Thu, 15 Dec 2022 13:25:01 -0500 Subject: [PATCH 1/8] Add STANAG 4607 packet/segment headers, mission segment --- CMakeLists.txt | 1 + arrows/CMakeLists.txt | 5 + arrows/stanag/CMakeLists.txt | 43 +++ arrows/stanag/stanag_4607_packet.cxx | 305 +++++++++++++++++++++ arrows/stanag/stanag_4607_packet.h | 208 ++++++++++++++ arrows/stanag/stanag_4607_segments.cxx | 364 +++++++++++++++++++++++++ arrows/stanag/stanag_4607_segments.h | 324 ++++++++++++++++++++++ arrows/stanag/stanag_util.cxx | 31 +++ arrows/stanag/stanag_util.h | 138 ++++++++++ 9 files changed, 1419 insertions(+) create mode 100644 arrows/stanag/CMakeLists.txt create mode 100644 arrows/stanag/stanag_4607_packet.cxx create mode 100644 arrows/stanag/stanag_4607_packet.h create mode 100644 arrows/stanag/stanag_4607_segments.cxx create mode 100644 arrows/stanag/stanag_4607_segments.h create mode 100644 arrows/stanag/stanag_util.cxx create mode 100644 arrows/stanag/stanag_util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d911507edc..217df5dc7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,7 @@ OPTION(KWIVER_ENABLE_SPROKIT "Enable building sprokit" OFF ) if(KWIVER_ENABLE_ARROWS) OPTION(KWIVER_ENABLE_MVG "Enable Multi-View Geometry Arrow" ON ) OPTION(KWIVER_ENABLE_KLV "Enable Key-Length-Value Metadata Arrow" ON) + OPTION(KWIVER_ENABLE_STANAG "Enable NATO Standardization Agreement Arrow" ON) endif() CMAKE_DEPENDENT_OPTION(KWIVER_ENABLE_PROCESSES diff --git a/arrows/CMakeLists.txt b/arrows/CMakeLists.txt index 85bdeaabd3..b0aff13ffb 100644 --- a/arrows/CMakeLists.txt +++ b/arrows/CMakeLists.txt @@ -89,6 +89,11 @@ if( KWIVER_ENABLE_KLV ) add_subdirectory( klv ) endif() +# if stanag is enabled +if( KWIVER_ENABLE_STANAG ) + add_subdirectory( stanag ) +endif() + # if GDAL is enabled if ( KWIVER_ENABLE_GDAL ) add_subdirectory( gdal ) diff --git a/arrows/stanag/CMakeLists.txt b/arrows/stanag/CMakeLists.txt new file mode 100644 index 0000000000..9c97474b3a --- /dev/null +++ b/arrows/stanag/CMakeLists.txt @@ -0,0 +1,43 @@ +# Build / Install STANAG Arrow + +set(CMAKE_FOLDER "Arrows/STANAG") + +set( sources + stanag_4607_packet.cxx + stanag_4607_segments.cxx + stanag_util.cxx + ) + +set( public_headers + stanag_4607_packet.h + stanag_4607_segments.h + stanag_util.h + ) + +kwiver_install_headers( + ${public_headers} + SUBDIR arrows/stanag + ) + +kwiver_install_headers( + ${CMAKE_CURRENT_BINARY_DIR}/kwiver_algo_stanag_export.h + NOPATH + SUBDIR arrows/stanag + ) + +kwiver_add_library( kwiver_algo_stanag + ${sources} + ${public_headers} + ) + +target_link_libraries( kwiver_algo_stanag + PUBLIC vital_algo + PRIVATE vital + vital_logger + kwiver_algo_klv kwiversys + ) + + +#if (KWIVER_ENABLE_TESTS) +# add_subdirectory( tests ) +#endif() diff --git a/arrows/stanag/stanag_4607_packet.cxx b/arrows/stanag/stanag_4607_packet.cxx new file mode 100644 index 0000000000..a7ffedf9b6 --- /dev/null +++ b/arrows/stanag/stanag_4607_packet.cxx @@ -0,0 +1,305 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_4607_packet.h" + +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, + stanag_4607_security_classification const& value ) +{ + std::map< stanag_4607_security_classification, std::string > strings + { + { STANAG_4607_SECURITY_CLASS_TOP_SECRET, "TOP SECRET" }, + { STANAG_4607_SECURITY_CLASS_SECRET, "SECRET" }, + { STANAG_4607_SECURITY_CLASS_CONFIDENTIAL, "CONFIDENTIAL" }, + { STANAG_4607_SECURITY_CLASS_RESTRICTED, "RESTRICTED" }, + { STANAG_4607_SECURITY_CLASS_UNCLASSIFIED, "UNCLASSIFIED" }, + { STANAG_4607_SECURITY_CLASS_ENUM_END, "Unknown Security Classification" } + }; + + os << strings[ std::min( value, STANAG_4607_SECURITY_CLASS_ENUM_END ) ]; + return os; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_security_code const& value ) +{ + std::map< stanag_4607_security_code, std::string > strings + { + { STANAG_4607_SECURITY_CODE_NONE, "NONE (NO-STATEMENT VALUE)" }, + { STANAG_4607_SECURITY_CODE_NOCONTRACT, "NO CONTRACT" }, + { STANAG_4607_SECURITY_CODE_ORCON, "ORCON" }, + { STANAG_4607_SECURITY_CODE_PROPIN, "PROPIN" }, + { STANAG_4607_SECURITY_CODE_WNINTEL, "WNINTEL" }, + { STANAG_4607_SECURITY_CODE_NATIONAL_ONLY, "NATIONAL ONLY" }, + { STANAG_4607_SECURITY_CODE_LIMDIS, "LIMDIS" }, + { STANAG_4607_SECURITY_CODE_FOUO, "FOUO" }, + { STANAG_4607_SECURITY_CODE_EFTO, "EFTO" }, + { STANAG_4607_SECURITY_CODE_LIM_OFF_USE, "LIM OFF USE (UNCLAS)" }, + { STANAG_4607_SECURITY_CODE_NONCOMPARTMENT, "NONCOMPARTMENT" }, + { STANAG_4607_SECURITY_CODE_SPECIAL_CONTROL, "SPECIAL CONTROL" }, + { STANAG_4607_SECURITY_CODE_SPECIAL_INTEL, "SPECIAL INTEL" }, + { STANAG_4607_SECURITY_CODE_WARNING_NOTICE, + "WARNING NOTICE – SECURITY CLASSIFICATION IS BASED ON THE FACT " + "OF EXISTENCE AND AVAIL OF THIS DATA" }, + { STANAG_4607_SECURITY_CODE_REL_NATO, "REL NATO (BEL, BGR, CAN, CZE, DNK, " + "EST, FRA, DEU, GRC, HUN, ISL, ITA, LVA, LTU, LUX,NLD, NOR, POL, PRT, " + "ROU, SVK, SVN, ESP, TUR, GBR, USA)" }, + { STANAG_4607_SECURITY_CODE_REL_4_EYES, + "REL 4-EYES (AUS, CAN, GBR, USA)" }, + { STANAG_4607_SECURITY_CODE_REL_9_EYES, + "REL 9-EYES (CAN, FRA, DEU, ITA, NLD, NOR, ESP, GBR, USA)" }, + { STANAG_4607_SECURITY_CODE_ENUM_END, "Unknown Security Code" } }; + + os << strings[ std::min( value, STANAG_4607_SECURITY_CODE_ENUM_END ) ]; + return os; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_packet_security const& value ) +{ + return os << "{ " + << "Classification: " << value.classification << ", " + << "Class. System: " << value.class_system << ", " + << "Code: " << value.code + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP( + stanag_4607_packet_security, + &stanag_4607_packet_security::classification, + &stanag_4607_packet_security::class_system, + &stanag_4607_packet_security::code +) + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_exercise_indicator const& value ) +{ + std::map strings + { { STANAG_4607_EXERCISE_IND_OPERATION_REAL, "Operation, Real Data" }, + { STANAG_4607_EXERCISE_IND_OPERATION_SIMULATED, + "Operation, Simulated Data" }, + { STANAG_4607_EXERCISE_IND_OPERATION_SYNTHESIZED, + "Operation, Synthesized Data" }, + { STANAG_4607_EXERCISE_IND_EXERCISE_REAL, "Exercise, Real Data" }, + { STANAG_4607_EXERCISE_IND_EXERCISE_SIMULATED, + "Exercise, Simulated Data" }, + { STANAG_4607_EXERCISE_IND_EXERCISE_SYNTHESIZED, + "Exercise, Synthesized Data" }, + { STANAG_4607_EXERCISE_IND_ENUM_END, "Unknown Exercise Indicator" } }; + + os << strings[ std::min( value, STANAG_4607_EXERCISE_IND_ENUM_END ) ]; + return os; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_packet_header const& value ) +{ + return os << "{ " + << "Version ID: " << value.version_id << ", " + << "Packet Size: " << value.packet_size << ", " + << "Nationality: " << value.nationality << ", " + << "Packet Security: " << value.packet_security << ", " + << "Exercise Indicator: " << value.exercise_indicator << ", " + << "Platform ID: " << value.platform_id << ", " + << "Mission ID: " << value.mission_id << ", " + << "Job ID: " << value.job_id + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP( + stanag_4607_packet_header, + &stanag_4607_packet_header::version_id, + &stanag_4607_packet_header::packet_size, + &stanag_4607_packet_header::nationality, + &stanag_4607_packet_header::packet_security, + &stanag_4607_packet_header::exercise_indicator, + &stanag_4607_packet_header::platform_id, + &stanag_4607_packet_header::mission_id, + &stanag_4607_packet_header::job_id +) + +// ---------------------------------------------------------------------------- +stanag_4607_packet_header_format +::stanag_4607_packet_header_format() +{} + +// ---------------------------------------------------------------------------- +stanag_4607_packet_header +stanag_4607_packet_header_format +::read( ptr_t& ptr ) const +{ + stanag_4607_packet_header result; + + result.version_id = klv::klv_read_string( ptr, (size_t)2 ); + + result.packet_size = klv::klv_read_int< size_t >( ptr, (size_t)4 ); + + result.nationality = klv::klv_read_string( ptr, (size_t)2 ); + + result.packet_security.classification = + static_cast< stanag_4607_security_classification >( + klv::klv_read_int< uint64_t >( ptr, (size_t)1 )); + result.packet_security.class_system = klv::klv_read_string( ptr, + (size_t)2 ); + result.packet_security.code = static_cast< stanag_4607_security_code >( + klv::klv_read_int< uint64_t >( ptr, (size_t)2 )); + + result.exercise_indicator = static_cast< stanag_4607_exercise_indicator >( + klv::klv_read_int< uint64_t >( ptr, (size_t)1 )); + + result.platform_id = trim_whitespace( klv::klv_read_string( ptr, + (size_t)10 ) ); + + result.mission_id = klv::klv_read_int< int >( ptr, (size_t)4 ); + + result.job_id = klv::klv_read_int< int >( ptr, (size_t)4 ); + + return result; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_packet const& value ) +{ + os << "{ " + << "Packet Header: " << value.header; + + auto num_segments = value.segment_headers.size(); + if( num_segments == 0 ) + { + return os << ", " << "Segment Header: (empty)" << ", " + << "(No segments)"; + } + for ( size_t i=0; i const& value ) +{ + if ( value.empty() ) + { + return os << "(empty)"; + } + for( auto v : value ) + { + os << v; + os << std::endl; + } + return os; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP( + stanag_4607_packet, + &stanag_4607_packet::header, + &stanag_4607_packet::segment_headers, + &stanag_4607_packet::segments +) + +// ---------------------------------------------------------------------------- +stanag_4607_packet_format +::stanag_4607_packet_format() +{} + +// ---------------------------------------------------------------------------- +stanag_4607_packet +stanag_4607_packet_format +::read( ptr_t& ptr ) const +{ + size_t bytes_read_in_packet = 0; + + // Read packet header + stanag_4607_packet_header_format packet_header; + + stanag_4607_packet_header packet_header_data = + packet_header.read( ptr ); + + bytes_read_in_packet += packet_header.size; + auto packet_size = packet_header_data.packet_size; + + std::vector< stanag_4607_segment_header > segment_headers; + // TODO: make this any segment type + std::vector< stanag_4607_mission_segment > segments; + + while( bytes_read_in_packet < packet_size ) + { + // Read segment header + stanag_4607_segment_header_format segment_header; + auto segment_header_data = segment_header.read( ptr ); + segment_headers.push_back( segment_header_data ); + + // Determine segment type + size from segment header + stanag_4607_segment_type type = segment_header_data.segment_type; + auto const& format = stanag_4607_segment_type_traits_lookup_table() + .by_type( type ).format(); + size_t segment_size = segment_header_data.segment_size; + + // Read message segment + auto message = format.read( ptr ); + segments.push_back( message ); + + bytes_read_in_packet += segment_size; + } + + stanag_4607_packet packet; + packet.header = packet_header_data; + packet.segment_headers = segment_headers; + packet.segments = segments; + + return packet; +} + +// ---------------------------------------------------------------------------- +std::vector< stanag_4607_packet > +read_stanag_4607_data( ptr_t& ptr ) +{ + + std::vector< stanag_4607_packet > result; + + // TODO loop over all packets + //while(ptr != &*input_bytes.cend() ) + //{ + stanag_4607_packet_format packet; + stanag_4607_packet packet_data = packet.read( ptr ); + result.push_back( packet_data ); + + //} + + //std::vector< stanag_4607_packet > result{ packet_data }; + + return result; +} + + +} // Namespace stanag + +} // Namespace arrows + +} // Namespace kwiver diff --git a/arrows/stanag/stanag_4607_packet.h b/arrows/stanag/stanag_4607_packet.h new file mode 100644 index 0000000000..b88e632aa6 --- /dev/null +++ b/arrows/stanag/stanag_4607_packet.h @@ -0,0 +1,208 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +/// \file +/// Defines a STANAG 4607 packet and packet header + +#ifndef KWIVER_ARROWS_STANAG_4607_PACKET_H_ +#define KWIVER_ARROWS_STANAG_4607_PACKET_H_ + +#include + +#include "stanag_4607_segments.h" +#include "stanag_util.h" + +namespace ka = kwiver::arrows; + +#include +#include +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +// ---------------------------------------------------------------------------- +/// Indicates the classification level of a packet +enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_security_classification +{ + STANAG_4607_SECURITY_CLASS_TOP_SECRET = 1, + STANAG_4607_SECURITY_CLASS_SECRET = 2, + STANAG_4607_SECURITY_CLASS_CONFIDENTIAL = 3, + STANAG_4607_SECURITY_CLASS_RESTRICTED = 4, + STANAG_4607_SECURITY_CLASS_UNCLASSIFIED = 5, + STANAG_4607_SECURITY_CLASS_ENUM_END, +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + stanag_4607_security_classification const& value ); + +// ---------------------------------------------------------------------------- +/// Indicates additional control and/or handling instructions associated +/// with the GMTI data +enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_security_code +{ + STANAG_4607_SECURITY_CODE_NONE = 0x0000, + STANAG_4607_SECURITY_CODE_NOCONTRACT = 0x0001, + STANAG_4607_SECURITY_CODE_ORCON = 0x0002, + STANAG_4607_SECURITY_CODE_PROPIN = 0x0004, + STANAG_4607_SECURITY_CODE_WNINTEL = 0x0008, + STANAG_4607_SECURITY_CODE_NATIONAL_ONLY = 0x0010, + STANAG_4607_SECURITY_CODE_LIMDIS = 0x0020, + STANAG_4607_SECURITY_CODE_FOUO = 0x0040, + STANAG_4607_SECURITY_CODE_EFTO = 0x0080, + STANAG_4607_SECURITY_CODE_LIM_OFF_USE = 0x0100, + STANAG_4607_SECURITY_CODE_NONCOMPARTMENT = 0x0200, + STANAG_4607_SECURITY_CODE_SPECIAL_CONTROL = 0x0400, + STANAG_4607_SECURITY_CODE_SPECIAL_INTEL = 0x0800, + STANAG_4607_SECURITY_CODE_WARNING_NOTICE = 0x1000, + STANAG_4607_SECURITY_CODE_REL_NATO = 0x2000, + STANAG_4607_SECURITY_CODE_REL_4_EYES = 0x4000, + STANAG_4607_SECURITY_CODE_REL_9_EYES = 0x8000, + STANAG_4607_SECURITY_CODE_ENUM_END, +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_security_code const& value ); + +// ---------------------------------------------------------------------------- +/// Security information for the packet +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet_security +{ + stanag_4607_security_classification classification; + std::string class_system; + stanag_4607_security_code code; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_packet_security const& value ); + + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_packet_security ) + +// ---------------------------------------------------------------------------- +/// Indicating whether the data contained in this packet is from a real-world +/// military operation or from an exercise, and whether the data is real, +/// simulated, or synthesized. +enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_exercise_indicator +{ + STANAG_4607_EXERCISE_IND_OPERATION_REAL = 0, + STANAG_4607_EXERCISE_IND_OPERATION_SIMULATED = 1, + STANAG_4607_EXERCISE_IND_OPERATION_SYNTHESIZED = 2, + // Note: 2-127 are reserved + STANAG_4607_EXERCISE_IND_EXERCISE_REAL = 128, + STANAG_4607_EXERCISE_IND_EXERCISE_SIMULATED = 129, + STANAG_4607_EXERCISE_IND_EXERCISE_SYNTHESIZED = 130, + // Note: 131-255 are reserved + STANAG_4607_EXERCISE_IND_ENUM_END = 256, +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_exercise_indicator const& value ); + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_packet_security const& value ); + +// ---------------------------------------------------------------------------- +/// Provides basic information concerning the platform, the job, the mission, +/// nationality, security, and the length of the packet. +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet_header +{ + std::string version_id; + size_t packet_size; // Includes header size + std::string nationality; + stanag_4607_packet_security packet_security; + stanag_4607_exercise_indicator exercise_indicator; + std::string platform_id; + int mission_id; + int job_id; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_packet_header const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_packet_header ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet_header_format + : public stanag_4607_packet_header +{ +public: + stanag_4607_packet_header_format(); + + + const size_t size = 32; // Number of bytes in packet header + + stanag_4607_packet_header + read( ptr_t& ptr ) const; +}; + + +// ---------------------------------------------------------------------------- +/// Top level STANAG 4607 packet +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet +{ + stanag_4607_packet_header header; + std::vector< stanag_4607_segment_header > segment_headers; + std::vector< stanag_4607_mission_segment > segments; // TODO: make this any + // segment type +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_packet const& value ); + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, std::vector< stanag_4607_packet > const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_packet ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet_format + : public stanag_4607_packet +{ +public: + stanag_4607_packet_format(); + + stanag_4607_packet + read( ptr_t& ptr ) const; +}; + + +// ---------------------------------------------------------------------------- +/// Read the input data as a list of packets +KWIVER_ALGO_STANAG_EXPORT +std::vector< stanag_4607_packet > +read_stanag_4607_data( ptr_t& ptr ); + +} // Namespace stanag + +} // Namespace arrows + +} // Namespace kwiver + +#endif diff --git a/arrows/stanag/stanag_4607_segments.cxx b/arrows/stanag/stanag_4607_segments.cxx new file mode 100644 index 0000000000..638e1c6dae --- /dev/null +++ b/arrows/stanag/stanag_4607_segments.cxx @@ -0,0 +1,364 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_4607_segments.h" + +namespace ka = kwiver::arrows; + +#include + +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits_lookup const& +stanag_4607_segment_type_traits_lookup_table() +{ + static stanag_4607_segment_type_traits_lookup const lookup = { + { + STANAG_4607_SEGMENT_TYPE_MISSION, "STANAG_4607_SEGMENT_TYPE_MISSION", + std::make_shared< stanag_4607_mission_segment_format >(), + "Mission Segment" + } + }; + + // TODO finish rest of segments + /* + { + STANAG_4607_SEGMENT_TYPE_DWELL, + std::make_shared<>(), + "Dwell Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_HRR, + std::make_shared<>(), + "HRR Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_JOB_DEFINITION, + std::make_shared<>(), + "Job Definition Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_FREE_TEXT, + std::make_shared<>(), + "Free Text Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_LOW_REFLECTIVITY_INDEX, + std::make_shared<>(), + "Low Reflectivity Index Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_GROUP, + std::make_shared<>(), + "Group Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_ATTACHED_TARGET, + std::make_shared<>(), + "Attached Target Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_TEST_AND_STATUS, + std::make_shared<>(), + "Test and Status Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_SYSTEM_SPECIFIC, + std::make_shared<>(), + "System-Specific Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_PROCESSING_HISTORY, + std::make_shared<>(), + "Processing History Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_PLATFORM_LOCATION, + std::make_shared<>(), + "Platform Location Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_JOB_REQUEST, + std::make_shared<>(), + "Job Request Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_JOB_ACKNOWLEDGE, + std::make_shared<>(), + "Job Acknowledge Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_ENUM_END, + std::make_shared<>(), + "Unknown STANAG4607 segment type" + } */ + //}; + + return lookup; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, + stanag_4607_segment_type const& value ) +{ + os << stanag_4607_segment_type_traits_lookup_table().by_type( value ) + .name(); + + return os; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_segment_header const& value ) +{ + os << "{ " + << "Segment Type: " << value.segment_type << ", " + << "Segment Size: " << value.segment_size + << " }"; + + return os; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP( + stanag_4607_segment_header, + &stanag_4607_segment_header::segment_type, + &stanag_4607_segment_header::segment_size +) + +// ---------------------------------------------------------------------------- +stanag_4607_segment_header_format +::stanag_4607_segment_header_format() +{} + +// ---------------------------------------------------------------------------- +stanag_4607_segment_header +stanag_4607_segment_header_format +::read( ptr_t& ptr ) const +{ + stanag_4607_segment_header result; + + result.segment_type = static_cast< stanag_4607_segment_type >( + ka::klv::klv_read_int< uint64_t >( ptr, 1 )); + result.segment_size = ka::klv::klv_read_int< size_t >( ptr, 4 ); + + return result; +} + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits_lookup +::stanag_4607_segment_type_traits_lookup( + std::initializer_list< stanag_4607_segment_type_traits > const& traits ) + : m_traits{ traits.begin(), traits.end() } +{ + initialize(); +} + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits_lookup +::stanag_4607_segment_type_traits_lookup( + std::vector< stanag_4607_segment_type_traits > const& traits ) + : m_traits{ traits.begin(), traits.end() } +{ + initialize(); +} + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits const& +stanag_4607_segment_type_traits_lookup +::by_type( uint16_t type ) const +{ + auto const result = m_type_to_traits.find( type ); + return ( result == m_type_to_traits.end() ) + ? m_traits.at( 0 ) + : *result->second; +} + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits const& +stanag_4607_segment_type_traits_lookup +::by_enum_name( std::string const& enum_name ) const +{ + auto const result = m_enum_name_to_traits.find( enum_name ); + return ( result == m_enum_name_to_traits.end() ) + ? m_traits.at( 0 ) + : *result->second; +} + +// ---------------------------------------------------------------------------- +void +stanag_4607_segment_type_traits_lookup +::initialize() +{ + if( m_traits.empty() ) + { + throw std::logic_error( "traits cannot be empty" ); + } + + for( auto const& trait : m_traits ) + { + if( trait.type() ) + { + m_type_to_traits.emplace( trait.type(), &trait ).second; + } + + if( !trait.enum_name().empty() ) + { + m_enum_name_to_traits.emplace( trait.enum_name(), &trait ).second; + } + } +} + +// ---------------------------------------------------------------------------- +stanag_4607_mission_segment_format +::stanag_4607_mission_segment_format() +{} + +// ---------------------------------------------------------------------------- +stanag_4607_mission_segment +stanag_4607_mission_segment_format +::read( ptr_t& ptr ) const +{ + stanag_4607_mission_segment result; + + result.mission_plan = trim_whitespace( klv::klv_read_string( ptr, + (size_t)12 ) ); + + result.flight_plan = trim_whitespace( klv::klv_read_string( ptr, + (size_t)12 ) ); + + result.platform_type = static_cast< stanag_4607_mission_segment_platform >( + klv::klv_read_int< uint64_t >( ptr, (size_t)1 )); + + result.platform_configuration = trim_whitespace( klv::klv_read_string( + ptr, (size_t)10 ) ); + + result.reference_time.year = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.reference_time.month = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.reference_time.day = klv::klv_read_int< int >( ptr, (size_t)1 ); + + return result; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, + stanag_4607_mission_segment_platform const& value ) +{ + std::map< stanag_4607_mission_segment_platform, std::string > strings + { + { STANAG_4607_MISSION_PLATFORM_UNIDENTIFIED, "Unidentified" }, + { STANAG_4607_MISSION_PLATFORM_ACS, "ACS" }, + { STANAG_4607_MISSION_PLATFORM_ARL_M, "ARL-M" }, + { STANAG_4607_MISSION_PLATFORM_SENTINEL, "Sentinel (was ASTOR)" }, + { STANAG_4607_MISSION_PLATFORM_ROTARY_WING_RADAR, + "Rotary Wing Radar (was CRESO)" }, + { STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_NAVY, "Global Hawk-Navy" }, + { STANAG_4607_MISSION_PLATFORM_HORIZON, "HORIZON" }, + { STANAG_4607_MISSION_PLATFORM_E_8, "E-8 (Joint STARS)" }, + { STANAG_4607_MISSION_PLATFORM_P_3C, "P-3C" }, + { STANAG_4607_MISSION_PLATFORM_PREDATOR, "Predator" }, + { STANAG_4607_MISSION_PLATFORM_RADARSAT2, "RADARSAT2" }, + { STANAG_4607_MISSION_PLATFORM_U_2, "U-2" }, + { STANAG_4607_MISSION_PLATFORM_E_10, "E-10 (was MC2A)" }, + { STANAG_4607_MISSION_PLATFORM_UGS_SINGLE, "UGS – Single" }, + { STANAG_4607_MISSION_PLATFORM_UGS_CLUSTER, "UGS – Cluster" }, + { STANAG_4607_MISSION_PLATFORM_GROUND_BASED, "Ground Based" }, + { STANAG_4607_MISSION_PLATFORM_UAV_MARINES, "UAV-Marines" }, + { STANAG_4607_MISSION_PLATFORM_UAV_NAVY, "UAV-Navy" }, + { STANAG_4607_MISSION_PLATFORM_UAV_AIR_FORCE, "UAV-Air Force" }, + { STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AIR_FORCE, + "Global Hawk- Air Force" }, + { STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AUSTRALIA, + "Global Hawk-Australia" }, + { STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_GERMANY, + "Global Hawk-Germany" }, + { STANAG_4607_MISSION_PLATFORM_PAUL_REVERE, "Paul Revere" }, + { STANAG_4607_MISSION_PLATFORM_MARINER_UAV, "Mariner UAV" }, + { STANAG_4607_MISSION_PLATFORM_BAC_11, "BAC-111" }, + { STANAG_4607_MISSION_PLATFORM_COYOTE, "Coyote" }, + { STANAG_4607_MISSION_PLATFORM_KING_AIR, "King Air" }, + { STANAG_4607_MISSION_PLATFORM_LIMIT, "LIMIT" }, + { STANAG_4607_MISSION_PLATFORM_NRL_NP_3B, "NRL NP-3B" }, + { STANAG_4607_MISSION_PLATFORM_SOSTAR_X, "SOSTAR-X" }, + { STANAG_4607_MISSION_PLATFORM_WATCHKEEPER, "WatchKeeper" }, + { STANAG_4607_MISSION_PLATFORM_ALLIANCE_GROUND_SURVEILLANCE, + "Alliance Ground Surveillance (AGS) (A321)" }, + { STANAG_4607_MISSION_PLATFORM_STRYKER, "Stryker" }, + { STANAG_4607_MISSION_PLATFORM_AGS, "AGS (HALE UAV)" }, + { STANAG_4607_MISSION_PLATFORM_SIDM, "SIDM" }, + { STANAG_4607_MISSION_PLATFORM_REAPER, "Reaper" }, + { STANAG_4607_MISSION_PLATFORM_WARRIOR_A, "Warrior A" }, + { STANAG_4607_MISSION_PLATFORM_WARRIOR, "Warrior" }, + { STANAG_4607_MISSION_PLATFORM_TWIN_OTTER, "Twin Otter" }, + { STANAG_4607_MISSION_PLATFORM_OTHER, "Other" }, + { STANAG_4607_MISSION_PLATFORM_ENUM_END, + "Unknown Mission Segment Platform Type" } + }; + + os << strings[ std::min( value, STANAG_4607_MISSION_PLATFORM_ENUM_END ) ]; + + return os; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, + stanag_4607_mission_reference_time const& value ) +{ + return os << "{ " + << "Year: " << value.year << ", " + << "Month: " << value.month << ", " + << "Day: " << value.day + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP( + stanag_4607_mission_reference_time, + &stanag_4607_mission_reference_time::year, + &stanag_4607_mission_reference_time::month, + &stanag_4607_mission_reference_time::day +) + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_mission_segment const& value ) +{ + return os << "{ " + << "Mission Plan: " << value.mission_plan << ", " + << "Flight Plan: " << value.flight_plan << ", " + << "Platform Type: " << value.platform_type << ", " + << "Platform Configuration: " << value.platform_configuration + << ", " + << "Reference Time: " << value.reference_time + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP( + stanag_4607_mission_segment, + &stanag_4607_mission_segment::mission_plan, + &stanag_4607_mission_segment::flight_plan, + &stanag_4607_mission_segment::platform_type, + &stanag_4607_mission_segment::platform_configuration, + &stanag_4607_mission_segment::reference_time +) + + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver diff --git a/arrows/stanag/stanag_4607_segments.h b/arrows/stanag/stanag_4607_segments.h new file mode 100644 index 0000000000..3b1ebbb2f1 --- /dev/null +++ b/arrows/stanag/stanag_4607_segments.h @@ -0,0 +1,324 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +/// \file +/// Defines a STANAG 4607 segment header and the various segment types + +#ifndef KWIVER_ARROWS_STANAG_4607_SEGMENTS_H_ +#define KWIVER_ARROWS_STANAG_4607_SEGMENTS_H_ + +#include "stanag_util.h" +#include + +#include +#include +#include +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +// ---------------------------------------------------------------------------- +/// The type of message contained in the segment +enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_type : uint16_t +{ + STANAG_4607_SEGMENT_TYPE_MISSION = 1, + STANAG_4607_SEGMENT_TYPE_DWELL = 2, + STANAG_4607_SEGMENT_TYPE_HRR = 3, + // Note: 4 is reserved + STANAG_4607_SEGMENT_TYPE_JOB_DEFINITION = 5, + STANAG_4607_SEGMENT_TYPE_FREE_TEXT = 6, + STANAG_4607_SEGMENT_TYPE_LOW_REFLECTIVITY_INDEX = 7, + STANAG_4607_SEGMENT_TYPE_GROUP = 8, + STANAG_4607_SEGMENT_TYPE_ATTACHED_TARGET = 9, + STANAG_4607_SEGMENT_TYPE_TEST_AND_STATUS = 10, + STANAG_4607_SEGMENT_TYPE_SYSTEM_SPECIFIC = 11, + STANAG_4607_SEGMENT_TYPE_PROCESSING_HISTORY = 12, + STANAG_4607_SEGMENT_TYPE_PLATFORM_LOCATION = 13, + // Note 14-100 are reserved for new segments + STANAG_4607_SEGMENT_TYPE_JOB_REQUEST = 101, + STANAG_4607_SEGMENT_TYPE_JOB_ACKNOWLEDGE = 102, + // Note: 103-127 are reserved for future use + // Note 128-255 are reserved for extensions + STANAG_4607_SEGMENT_TYPE_ENUM_END = 256, +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + stanag_4607_segment_type const& value ); + +// ---------------------------------------------------------------------------- +/// Identifies the type and size of the segment that follows +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_header +{ + stanag_4607_segment_type segment_type; + size_t segment_size; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_segment_header const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_segment_header ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_header_format + : public stanag_4607_segment_header +{ +public: + stanag_4607_segment_header_format(); + + + const size_t size = 5; // Number of bytes in the segment header + + stanag_4607_segment_header + read( ptr_t& ptr ) const; +}; + + +// ---------------------------------------------------------------------------- +/// Identifies the type of platform that originated the data +enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment_platform +{ + STANAG_4607_MISSION_PLATFORM_UNIDENTIFIED, + STANAG_4607_MISSION_PLATFORM_ACS, + STANAG_4607_MISSION_PLATFORM_ARL_M, + STANAG_4607_MISSION_PLATFORM_SENTINEL, + STANAG_4607_MISSION_PLATFORM_ROTARY_WING_RADAR, + STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_NAVY, + STANAG_4607_MISSION_PLATFORM_HORIZON, + STANAG_4607_MISSION_PLATFORM_E_8, + STANAG_4607_MISSION_PLATFORM_P_3C, + STANAG_4607_MISSION_PLATFORM_PREDATOR, + STANAG_4607_MISSION_PLATFORM_RADARSAT2, + STANAG_4607_MISSION_PLATFORM_U_2, + STANAG_4607_MISSION_PLATFORM_E_10, + STANAG_4607_MISSION_PLATFORM_UGS_SINGLE, + STANAG_4607_MISSION_PLATFORM_UGS_CLUSTER, + STANAG_4607_MISSION_PLATFORM_GROUND_BASED, + STANAG_4607_MISSION_PLATFORM_UAV_MARINES, + STANAG_4607_MISSION_PLATFORM_UAV_NAVY, + STANAG_4607_MISSION_PLATFORM_UAV_AIR_FORCE, + STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AIR_FORCE, + STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AUSTRALIA, + STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_GERMANY, + STANAG_4607_MISSION_PLATFORM_PAUL_REVERE, + STANAG_4607_MISSION_PLATFORM_MARINER_UAV, + STANAG_4607_MISSION_PLATFORM_BAC_11, + STANAG_4607_MISSION_PLATFORM_COYOTE, + STANAG_4607_MISSION_PLATFORM_KING_AIR, + STANAG_4607_MISSION_PLATFORM_LIMIT, + STANAG_4607_MISSION_PLATFORM_NRL_NP_3B, + STANAG_4607_MISSION_PLATFORM_SOSTAR_X, + STANAG_4607_MISSION_PLATFORM_WATCHKEEPER, + STANAG_4607_MISSION_PLATFORM_ALLIANCE_GROUND_SURVEILLANCE, + STANAG_4607_MISSION_PLATFORM_STRYKER, + STANAG_4607_MISSION_PLATFORM_AGS, + STANAG_4607_MISSION_PLATFORM_SIDM, + STANAG_4607_MISSION_PLATFORM_REAPER, + STANAG_4607_MISSION_PLATFORM_WARRIOR_A, + STANAG_4607_MISSION_PLATFORM_WARRIOR, + STANAG_4607_MISSION_PLATFORM_TWIN_OTTER, + // Note: 40-254 are available for future use + STANAG_4607_MISSION_PLATFORM_OTHER = 255, + STANAG_4607_MISSION_PLATFORM_ENUM_END, +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + stanag_4607_mission_segment_platform const& value ); + +// ---------------------------------------------------------------------------- +/// UTC time in which the mission originated +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_reference_time +{ + int year; + int month; + int day; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + stanag_4607_mission_reference_time const& value ); + + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_mission_reference_time ) + +// ---------------------------------------------------------------------------- +/// Information concerning the mission +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment +{ + std::string mission_plan; + std::string flight_plan; + stanag_4607_mission_segment_platform platform_type; + std::string platform_configuration; + stanag_4607_mission_reference_time reference_time; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_mission_segment const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_mission_segment ) + +// ---------------------------------------------------------------------------- +/// Untyped base for STANAG formats +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_data_format +{ +public: + explicit + stanag_4607_segment_data_format() {} + + virtual + ~stanag_4607_segment_data_format() = default; + + virtual stanag_4607_mission_segment // TODO: make this any segment type + read( ptr_t& ptr ) const = 0; +}; + +using stanag_4607_segment_data_format_sptr = + std::shared_ptr< stanag_4607_segment_data_format >; + +// ---------------------------------------------------------------------------- +/// Typed base for STANAG formats +template < class T > +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_data_format_ + : public stanag_4607_segment_data_format +{ +public: + using data_type = T; + + explicit + stanag_4607_segment_data_format_() + {} + + virtual + ~stanag_4607_segment_data_format_() {} + + virtual T + read( ptr_t& ptr ) const = 0; +}; + +// ---------------------------------------------------------------------------- +/// The type, enumeration, and name of a segment +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_type_traits +{ +public: + stanag_4607_segment_type_traits( uint16_t type, + std::string const& enum_name, + stanag_4607_segment_data_format_sptr format, + std::string const& name ) + : m_type{ type }, m_enum_name{ enum_name }, m_format{ format }, + m_name{ name } + {} + + /// Returns the enumeration value of the segment + uint16_t + type() const { return m_type; } + + /// Return a string version of the segment enumeration + std::string + enum_name() const { return m_enum_name; } + + /// Return the data format used to represent this segment's value. + stanag_4607_segment_data_format& + format() const { return *m_format; } + + /// Return the segment's name. + std::string + name() const { return m_name; } + +private: + uint16_t m_type; + std::string m_enum_name; + stanag_4607_segment_data_format_sptr m_format; + std::string m_name; +}; + +// ---------------------------------------------------------------------------- +/// Lookup table used to match a segment to its traits +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_type_traits_lookup +{ +public: + using iterator = + typename std::vector< stanag_4607_segment_type_traits >::const_iterator; + using init_list = + typename std::initializer_list< stanag_4607_segment_type_traits >; + + stanag_4607_segment_type_traits_lookup( + std::initializer_list< stanag_4607_segment_type_traits > const& traits ); + + stanag_4607_segment_type_traits_lookup( + std::vector< stanag_4607_segment_type_traits > const& traits ); + + iterator + begin() const { return m_traits.begin(); } + + iterator + end() const { return m_traits.end(); } + + stanag_4607_segment_type_traits const& + by_type( uint16_t type ) const; + + /// Return the traits object with \p enum_name as its enum name. + stanag_4607_segment_type_traits const& + by_enum_name( std::string const& enum_name ) const; + +private: + void initialize(); + + + std::vector< stanag_4607_segment_type_traits > m_traits; + std::map< std::string, + stanag_4607_segment_type_traits const* > m_enum_name_to_traits; + std::map< uint16_t, + stanag_4607_segment_type_traits const* > m_type_to_traits; +}; + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment_format + : public stanag_4607_segment_data_format_< stanag_4607_mission_segment > +{ +public: + stanag_4607_mission_segment_format(); + + + const size_t size = 39; // Number of bytes in mission segment + + stanag_4607_mission_segment + read( ptr_t& ptr ) const override; +}; + +// ---------------------------------------------------------------------------- +/// +// TODO DWELL + +// ---------------------------------------------------------------------------- +/// Return a traits lookup object for segment types. +stanag_4607_segment_type_traits_lookup const& +stanag_4607_segment_type_traits_lookup_table(); + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver + +#endif diff --git a/arrows/stanag/stanag_util.cxx b/arrows/stanag/stanag_util.cxx new file mode 100644 index 0000000000..b7e6a7b507 --- /dev/null +++ b/arrows/stanag/stanag_util.cxx @@ -0,0 +1,31 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_util.h" + +namespace klv = kwiver::arrows::klv; + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +// ---------------------------------------------------------------------------- +std::string +trim_whitespace( std::string input ) +{ + if( input == "" ) { return ""; } + + const auto str_begin = input.find_first_not_of( " \t" ); + const auto str_end = input.find_last_not_of( " \t" ); + + return input.substr( str_begin, ( str_end - str_begin ) + 1 ); +} + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver diff --git a/arrows/stanag/stanag_util.h b/arrows/stanag/stanag_util.h new file mode 100644 index 0000000000..4fc8808915 --- /dev/null +++ b/arrows/stanag/stanag_util.h @@ -0,0 +1,138 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +/// \file +/// Declaration of internal STANAG utility functions. + +#ifndef KWIVER_ARROWS_STANAG_STANAG_UTIL_H_ +#define KWIVER_ARROWS_STANAG_STANAG_UTIL_H_ + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +namespace klv = kwiver::arrows::klv; + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +using ptr_t = uint8_t const*; + +namespace klv = kwiver::arrows::klv; + +// Redefine some statements from klv_util.h in order to change the EXPORT +// ---------------------------------------------------------------------------- +#define DECLARE_STANAG_CMP( T ) \ + KWIVER_ALGO_STANAG_EXPORT bool operator<( T const&, T const& ); \ + KWIVER_ALGO_STANAG_EXPORT bool operator>( T const&, T const& ); \ + KWIVER_ALGO_STANAG_EXPORT bool operator<=( T const&, T const& ); \ + KWIVER_ALGO_STANAG_EXPORT bool operator>=( T const&, T const& ); \ + KWIVER_ALGO_STANAG_EXPORT bool operator==( T const&, T const& ); + +// ---------------------------------------------------------------------------- +#define DECLARE_STANAG_TEMPLATE_CMP( TYPE ) \ + template < class T > KWIVER_ALGO_STANAG_EXPORT bool operator<( \ + TYPE const&, TYPE const& ); \ + template < class T > KWIVER_ALGO_STANAG_EXPORT bool operator>( \ + TYPE const&, TYPE const& ); \ + template < class T > KWIVER_ALGO_STANAG_EXPORT bool operator<=( \ + TYPE const&, TYPE const& ); \ + template < class T > KWIVER_ALGO_STANAG_EXPORT bool operator>=( \ + TYPE const&, TYPE const& ); \ + template < class T > KWIVER_ALGO_STANAG_EXPORT bool operator==( \ + TYPE const&, TYPE const& ); + +// ---------------------------------------------------------------------------- +#define DEFINE_STANAG_STRUCT_CMP( T, ... ) \ + bool \ + operator<( T const& lhs, T const& rhs ) { return klv::struct_lt( lhs, \ + rhs, \ + __VA_ARGS__ ); \ + } \ + bool \ + operator>( T const& lhs, T const& rhs ) { return klv::struct_gt( lhs, \ + rhs, \ + __VA_ARGS__ ); \ + } \ + bool \ + operator<=( T const& lhs, T const& rhs ) { return klv::struct_le( lhs, \ + rhs, \ + __VA_ARGS__ ); \ + } \ + bool \ + operator>=( T const& lhs, T const& rhs ) { return klv::struct_ge( lhs, \ + rhs, \ + __VA_ARGS__ ); \ + } \ + bool \ + operator==( T const& lhs, T const& rhs ) { return klv::struct_eq( lhs, \ + rhs, \ + __VA_ARGS__ ); \ + } + +// ---------------------------------------------------------------------------- +#define DEFINE_STANAG_TEMPLATE_CMP( TYPE, ... ) \ + template < class T > bool \ + operator<( TYPE const& lhs, TYPE const& rhs ) { return klv::struct_lt( \ + lhs, rhs, \ + __VA_ARGS__ ); } \ + template < class T > bool \ + operator>( TYPE const& lhs, TYPE const& rhs ) { return klv::struct_gt( \ + lhs, rhs, \ + __VA_ARGS__ ); } \ + template < class T > bool \ + operator<=( TYPE const& lhs, TYPE const& rhs ) { return klv::struct_le( \ + lhs, rhs, \ + __VA_ARGS__ ); } \ + template < class T > bool \ + operator>=( TYPE const& lhs, TYPE const& rhs ) { return klv::struct_ge( \ + lhs, rhs, \ + __VA_ARGS__ ); } \ + template < class T > bool \ + operator==( TYPE const& lhs, TYPE const& rhs ) { return klv::struct_eq( \ + lhs, rhs, \ + __VA_ARGS__ ); } + +// ---------------------------------------------------------------------------- +#define DEFINE_STANAG_STRUCT_CMP_TUPLIZE( T ) \ + bool \ + operator<( T const& lhs, \ + T const& rhs ) { return tuplize( lhs ) < tuplize( rhs ); } \ + bool \ + operator>( T const& lhs, \ + T const& rhs ) { return tuplize( lhs ) > tuplize( rhs ); } \ + bool \ + operator<=( T const& lhs, \ + T const& rhs ) { return tuplize( lhs ) <= tuplize( rhs ); } \ + bool \ + operator>=( T const& lhs, \ + T const& rhs ) { return tuplize( lhs ) >= tuplize( rhs ); } \ + bool \ + operator==( T const& lhs, \ + T const& rhs ) { return tuplize( lhs ) == tuplize( rhs ); } + +// ---------------------------------------------------------------------------- +/// Trim leading and traling spaces from strings +KWIVER_ALGO_STANAG_EXPORT +std::string +trim_whitespace( std::string input ); + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver + +#endif From f969ba032be7e5f48a51558cf3509c7a6c45ec6d Mon Sep 17 00:00:00 2001 From: Hannah DeFazio Date: Thu, 22 Dec 2022 14:57:13 -0500 Subject: [PATCH 2/8] Add dwell segment, file reorg --- arrows/stanag/CMakeLists.txt | 10 +- .../segments/stanag_4607_dwell_segment.cxx | 838 ++++++++++++++++++ .../segments/stanag_4607_dwell_segment.h | 450 ++++++++++ .../stanag_4607_mission_segment.cxx} | 264 +----- .../segments/stanag_4607_mission_segment.h | 140 +++ .../segments/stanag_4607_segment_lookup.cxx | 206 +++++ .../segments/stanag_4607_segment_lookup.h | 123 +++ .../stanag/segments/stanag_4607_segments.cxx | 63 ++ arrows/stanag/segments/stanag_4607_segments.h | 136 +++ arrows/stanag/stanag_4607_packet.cxx | 61 +- arrows/stanag/stanag_4607_packet.h | 21 +- arrows/stanag/stanag_4607_segments.h | 324 ------- arrows/stanag/stanag_util.cxx | 2 + arrows/stanag/stanag_util.h | 2 + 14 files changed, 2054 insertions(+), 586 deletions(-) create mode 100644 arrows/stanag/segments/stanag_4607_dwell_segment.cxx create mode 100644 arrows/stanag/segments/stanag_4607_dwell_segment.h rename arrows/stanag/{stanag_4607_segments.cxx => segments/stanag_4607_mission_segment.cxx} (54%) create mode 100644 arrows/stanag/segments/stanag_4607_mission_segment.h create mode 100644 arrows/stanag/segments/stanag_4607_segment_lookup.cxx create mode 100644 arrows/stanag/segments/stanag_4607_segment_lookup.h create mode 100644 arrows/stanag/segments/stanag_4607_segments.cxx create mode 100644 arrows/stanag/segments/stanag_4607_segments.h delete mode 100644 arrows/stanag/stanag_4607_segments.h diff --git a/arrows/stanag/CMakeLists.txt b/arrows/stanag/CMakeLists.txt index 9c97474b3a..6edf388fcb 100644 --- a/arrows/stanag/CMakeLists.txt +++ b/arrows/stanag/CMakeLists.txt @@ -4,14 +4,20 @@ set(CMAKE_FOLDER "Arrows/STANAG") set( sources stanag_4607_packet.cxx - stanag_4607_segments.cxx stanag_util.cxx + segments/stanag_4607_segments.cxx + segments/stanag_4607_segment_lookup.cxx + segments/stanag_4607_mission_segment.cxx + segments/stanag_4607_dwell_segment.cxx ) set( public_headers stanag_4607_packet.h - stanag_4607_segments.h stanag_util.h + segments/stanag_4607_segments.h + segments/stanag_4607_segment_lookup.h + segments/stanag_4607_mission_segment.h + segments/stanag_4607_dwell_segment.h ) kwiver_install_headers( diff --git a/arrows/stanag/segments/stanag_4607_dwell_segment.cxx b/arrows/stanag/segments/stanag_4607_dwell_segment.cxx new file mode 100644 index 0000000000..a76c47dad0 --- /dev/null +++ b/arrows/stanag/segments/stanag_4607_dwell_segment.cxx @@ -0,0 +1,838 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_4607_dwell_segment.h" + +namespace ka = kwiver::arrows; + +#include +#include + + +#include +#include +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_sensor_position const& value ) +{ + return os << "{ " + << "Latitude: " << value.latitude << " degrees" << ", " + << "Longitude: " << value.longitude << " degrees" << ", " + << "Altitude: " << value.altitude << " cm" + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP ( + stanag_4607_sensor_position, + &stanag_4607_sensor_position::latitude, + &stanag_4607_sensor_position::longitude, + &stanag_4607_sensor_position::altitude +) + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_scale_factor const& value ) +{ + return os << "{ " + << "Lat Scale: " << value.lat_scale << " degrees" << ", " + << "Long Scale: " << value.long_scale << " degrees" + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP ( + stanag_4607_scale_factor, + &stanag_4607_scale_factor::lat_scale, + &stanag_4607_scale_factor::long_scale +) + +// ---------------------------------------------------------------------------- +stanag_4607_scale_factor +stanag_4607_scale_factor_format +::read( ptr_t& ptr ) const +{ + stanag_4607_scale_factor result; + + result.lat_scale = klv::klv_read_int< int >( ptr, (size_t)4 ); + result.long_scale = klv::klv_read_int< int >( ptr, (size_t)4 ); + + return result; + +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_sensor_pos_uncert const& value ) +{ + return os << "{ " + << "Along Track: " << value.along_track << " cm" << ", " + << "Cross Track: " << value.cross_track << " cm" << ", " + << "Altitude: " << value.altitude << " cm" + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP ( + stanag_4607_sensor_pos_uncert, + &stanag_4607_sensor_pos_uncert::along_track, + &stanag_4607_sensor_pos_uncert::cross_track, + &stanag_4607_sensor_pos_uncert::altitude +) + +// ---------------------------------------------------------------------------- +stanag_4607_sensor_pos_uncert +stanag_4607_sensor_pos_uncert_format +::read( ptr_t& ptr ) const +{ + stanag_4607_sensor_pos_uncert result; + + result.along_track = klv::klv_read_int< int >( ptr, (size_t)4 ); + result.cross_track = klv::klv_read_int< int >( ptr, (size_t)4 ); + result.altitude = klv::klv_read_int< int >( ptr, (size_t)2 ); + + return result; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_orientation const& value ) +{ + return os << "{ " + << "Heading: " << value.heading << " degrees" << ", " + << "Pitch: " << value.pitch << " degrees" << ", " + << "Roll: " << value.roll << " degrees" + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP ( + stanag_4607_orientation, + &stanag_4607_orientation::heading, + &stanag_4607_orientation::pitch, + &stanag_4607_orientation::roll +) + +// ---------------------------------------------------------------------------- +stanag_4607_orientation +stanag_4607_orientation_format +::read( ptr_t& ptr ) const +{ + stanag_4607_orientation result; + + result.heading = klv::klv_read_flint< uint16_t >({0, 369.9945}, ptr, 2); + result.pitch = klv::klv_read_flint< int16_t >({-90, 90}, ptr, 2); + result.roll = klv::klv_read_flint< int16_t >({-90, 90}, ptr, 2); + + return result; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_dwell_area const& value ) +{ + return os << "{ " + << "Center Latitude: " << value.center_lat << " degrees" << ", " + << "Center Longitude: " << value.center_long << " degrees" << ", " + << "Range Half Extent: " << value.range_half_ext << " km" << ", " + << "Dwell Angle Half Extent: " << value.dwell_angle_half_ext + << " degrees" + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP ( + stanag_4607_dwell_area, + &stanag_4607_dwell_area::center_lat, + &stanag_4607_dwell_area::center_long, + &stanag_4607_dwell_area::range_half_ext, + &stanag_4607_dwell_area::dwell_angle_half_ext +) + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, + stanag_4607_target_classification const& value ) +{ + std::map< stanag_4607_target_classification, std::string > strings + { + { STANAG_4607_TARGET_CLASS_NO_INFO_LIVE, "No Information, Live Target" }, + { STANAG_4607_TARGET_CLASS_TRACKED_VEHICLE_LIVE, + "Tracked Vehicle, Live Target" }, + { STANAG_4607_TARGET_CLASS_WHEELED_VEHICLE_LIVE, + "Wheeled Vehicle, Live Target" }, + { STANAG_4607_TARGET_CLASS_ROTARY_WING_AIRCRAFT_LIVE, + "Rotary Wing Aircraft, Live Target"} , + { STANAG_4607_TARGET_CLASS_FIXED_WING_AIRCRAFT_LIVE, + "Fixed Wing Aircraft, Live Target" }, + { STANAG_4607_TARGET_CLASS_STATIONARY_ROTATOR_LIVE, + "Stationary Rotator, Live Target" }, + { STANAG_4607_TARGET_CLASS_MARITIME_LIVE, "Maritime, Live Target" }, + { STANAG_4607_TARGET_CLASS_BEACON_LIVE, "Beacon, Live Target" }, + { STANAG_4607_TARGET_CLASS_AMPHIBIOUS_LIVE, "Amphibious, Live Target" }, + { STANAG_4607_TARGET_CLASS_PERSON_LIVE, "Person, Live Target" }, + { STANAG_4607_TARGET_CLASS_VEHICLE_LIVE, "Vehicle, Live Target" }, + { STANAG_4607_TARGET_CLASS_ANIMAL_LIVE, "Animal, Live Target" }, + { STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_LIVE_LAND, + "Large Multiple-Return, Live Land Target" }, + { STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_LIVE_MARITIME, + "Large Multiple-Return, Live Maritime Target" }, + { STANAG_4607_TARGET_CLASS_OTHER_LIVE, "Other, Live Target" }, + { STANAG_4607_TARGET_CLASS_UNKNOWN_LIVE, "Unknown, Live Target" }, + { STANAG_4607_TARGET_CLASS_NO_INFO_SIM, + "No Information, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_TRACKED_VEHICLE_SIM, + "Tracked Vehicle, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_WHEELED_VEHICLE_SIM, + "Wheeled Vehicle, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_ROTARY_WING_AIRCRAFT_SIM, + "Rotary Wing Aircraft, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_FIXED_WING_AIRCRAFT_SIM, + "Fixed Wing Aircraft, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_STATIONARY_ROTATOR_SIM, + "Stationary Rotator, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_MARITIME_SIM, "Maritime, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_BEACON_SIM, "Beacon, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_AMPHIBIOUS_SIM, + "Amphibious, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_PERSON_SIM, "Person, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_VEHICLE_SIM, "Vehicle, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_ANIMAL_SIM, "Animal, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_SIM_LAND, + "Large Multiple-Return, Simulated Land Target" }, + { STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_SIM_MARITIME, + "Large Multiple-Return, Simulated Maritime Target" }, + { STANAG_4607_TARGET_CLASS_TAGGING_DEVICE, "Tagging Device" }, + { STANAG_4607_TARGET_CLASS_OTHER_SIM, "Other, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_UNKNOWN_SIM, "Unknown, Simulated Target" }, + { STANAG_4607_TARGET_CLASS_ENUM_END, "Unknown Target Classification" } + }; + + os << strings[ std::min( value, STANAG_4607_TARGET_CLASS_ENUM_END ) ]; + + return os; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_target_measure_uncert const& value ) +{ + return os << "{ " + << "Slant Range: " << value.slant_range << " cm" << ", " + << "Cross Range: " << value.cross_range << " dm" << ", " + << "Height: " << value.height << " m" << ", " + << "Target Radial Velocity: " << value.radial_velocity << " cm/sec" + << " }"; + +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP ( + stanag_4607_target_measure_uncert, + &stanag_4607_target_measure_uncert::slant_range, + &stanag_4607_target_measure_uncert::cross_range, + &stanag_4607_target_measure_uncert::height, + &stanag_4607_target_measure_uncert::radial_velocity +) +// ---------------------------------------------------------------------------- +stanag_4607_target_measure_uncert +stanag_4607_target_measure_uncert_format +::read( ptr_t& ptr ) const +{ + stanag_4607_target_measure_uncert result; + + result.slant_range = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.cross_range = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.height = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.radial_velocity = klv::klv_read_int< int >( ptr, (size_t)2 ); + + return result; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_truth_tag const& value ) +{ + return os << "{ " + << "Application: " << value.application << ", " + << "Entity: " << value.entity + << " }"; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP ( + stanag_4607_truth_tag, + &stanag_4607_truth_tag::application, + &stanag_4607_truth_tag::entity +) + +// ---------------------------------------------------------------------------- +stanag_4607_truth_tag +stanag_4607_truth_tag_format +::read( ptr_t& ptr ) const +{ + stanag_4607_truth_tag result; + + result.application = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.entity = klv::klv_read_int< int >( ptr, (size_t)4 ); + + return result; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, + stanag_4607_dwell_existence_mask_bit const& value ) +{ + static std::string strings[ STANAG_4607_DWELL_EXIST_MASK_BIT_REVISIT_INDEX + + 1 ] = + { + "Target Report: Radar Cross Section Transmitted", + "Target Report: Truth Tag: Entity Transmitted", + "Target Report: Truth Tag: Application Transmitted", + "Target Report: Measurement Uncertainty: Radial Velocity Transmitted", + "Target Report: Measurement Uncertainty: Height Transmitted", + "Target Report: Measurement Uncertainty: Cross Range Transmitted", + "Target Report: Measurement Uncertainty: Slant Range Transmitted", + "Target Report: Class. Probability Transmitted", + "Target Report: Classification Transmitted", + "Target Report: SNR Transmitted", + "Target Report: Wrap Velocity Transmitted", + "Target Report: Velocity Line-of-Sight Component Transmitted", + "Target Report: Location: Geodetic Height Transmitted", + "Target Report: Location: Delta Long Transmitted", + "Target Report: Location: Delta Lat Transmitted", + "Target Report: Location: Hi-Res Longitude Transmitted", + "Target Report: Location: Hi-Res Latitude Transmitted", + "Target Report: MTI Report Index Transmitted", + "Minimum Detectable Velocity Transmitted", + "Sensor Orientation: Roll Transmitted", + "Sensor Orientation: Pitch Transmitted", + "Sensor Orientation: Heading Transmitted", + "Dwell Area: Dwell Angle Half Extent Transmitted", + "Dwell Area: Range Half Extent Transmitted", + "Dwell Area: Center Longitude Transmitted", + "Dwell Area: Center Latitude Transmitted", + "Platform Orientation: Roll Transmitted", + "Platform Orientation: Pitch Transmitted", + "Platform Orientation: Heading Transmitted", + "Sensor Vertical Velocity Uncertainty Transmitted", + "Sensor Speed Uncertainty Transmitted", + "Sensor Track Uncertainty Transmitted", + "Sensor Vertical Velocity Transmitted", + "Sensor Speed Transmitted", + "Sensor Track Transmitted", + "Sensor Position Uncertainty: Altitude Transmitted", + "Sensor Position Uncertainty: Cross Track Transmitted", + "Sensor Position Uncertainty: Along Track Transmitted", + "Scale Factor: Long Scale Transmitted", + "Scale Factor: Lat Scale Transmitted", + "Sensor Position: Altitude Transmitted", + "Sensor Position: Longitude Transmitted", + "Sensor Position: Latitude Transmitted", + "Dwell Time Transmitted", + "Target Report Count Transmitted", + "Last Dwell of Revisit Transmitted", + "Dwell Index Transmitted", + "Revisit Index Transmitted" + }; + + os << strings[ value ]; + return os; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_target_location const& value ) +{ + os << "{ "; + + if( value.hi_res_lat ) + { + os << "Hi-Res Latitude: " << *value.hi_res_lat << " degrees" << ", " + << "Hi-Res Longitude: " << *value.hi_res_long << " degrees" << ", "; + } + + if( value.delta_lat ) + { + os << "Delta Lat: " << *value.delta_lat << ", " + << "Delta Long: " << *value.delta_long << ", "; + } + + if( value.geodetic_height ) + { + os << "Geodetic Height: " << *value.geodetic_height << " m"; + } + + os << " }"; + + return os; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP ( + stanag_4607_target_location, + &stanag_4607_target_location::hi_res_lat, + &stanag_4607_target_location::hi_res_long, + &stanag_4607_target_location::delta_lat, + &stanag_4607_target_location::delta_long, + &stanag_4607_target_location::geodetic_height +) + +// ---------------------------------------------------------------------------- +stanag_4607_target_location +stanag_4607_target_location_format +::read( ptr_t& ptr, + std::set< stanag_4607_dwell_existence_mask_bit > existence_mask ) const +{ + stanag_4607_target_location result; + + // Fields D32.2-D32.3 are conditional and always sent together + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_HI_RES_LAT) ) + { + result.hi_res_lat = klv::klv_read_flint< int32_t >({-90, 90}, ptr, 4); + result.hi_res_long = klv::klv_read_flint< uint32_t >({0, 359.999999916}, + ptr, 4); + } + // Fields D32.4-D32.5 are conditional and always sent together + // Condition: Sent if D32.2 and D32.3 are not sent + else{ + result.delta_lat = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.delta_long = klv::klv_read_int< int >( ptr, (size_t)2 ); + } + + // Field D32.6 is optional + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_GEODETIC_HEIGHT) + ) + { + result.geodetic_height = klv::klv_read_int< int >( ptr, (size_t)2 ); + } + + return result; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_target_report const& value ) +{ + os << "{ "; + if ( value.mti_report_idx ) + { + os << "MTI Report Index: " << *value.mti_report_idx << ", "; + } + + if( value.location ) + { + os << "Target Location: " << *value.location << ", "; + } + + if( value.velocity_los ) + { + os << "Target Velocity Line-of-Sight Component: " << *value.velocity_los + << " cm/sec" << ", " + << "Target Wrap Velocity: " << *value.wrap_velocity << " cm/sec" + << ", "; + } + + if( value.snr ) + { + os << "Target SNR: " << *value.snr << " dB" << ", "; + } + + if( value.classification ) + { + os << "Target Classification: " << *value.classification << ", "; + } + + if( value.class_probability ) + { + os << "Target Class. Probability: " << *value.class_probability << " %" + << ", "; + } + + if( value.measurement_uncert ) + { + os << "Target Measurement Uncertainty: " << *value.measurement_uncert + << ", "; + } + + if( value.truth_tag ) + { + os << "Truth Tag: " << *value.truth_tag << ", "; + } + + if( value.radar_cross_sect ) + { + os << "Target Radar Cross Section:" << *value.radar_cross_sect + << " dB/2"; + } + + os << " }"; + return os; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, + std::vector< stanag_4607_target_report > const& value ) +{ + auto num_targets = value.size(); + + os << "{ "; + + if( num_targets == 0 ) + { + return os << "(empty) }"; + } + + for( size_t i=0; i existence_mask ) const +{ + stanag_4607_target_report result; + + // Field D32.1 is conditional + // Condition: Send if an HRR report is provided for targets in this dwell + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_MTI_REPORT_IDX) ) + { + result.mti_report_idx = klv::klv_read_int< int >( ptr, (size_t)2 ); + } + + result.location = stanag_4607_target_location_format{} + .read( ptr, existence_mask ); + + // Fields D32.7-D32.8 are optional and always sent together + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_VEL_LOS) ) + { + result.velocity_los = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.wrap_velocity = klv::klv_read_int< int >( ptr, (size_t)2 ); + } + + // Field D32.9 is optional + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_SNR) ) + { + result.snr = klv::klv_read_int< int >( ptr, (size_t)1 ); + } + + // Field D32.10 is optional + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_CLASS) ) + { + result.classification = static_cast< stanag_4607_target_classification >( + klv::klv_read_int< uint64_t >( ptr, (size_t)1 )); + } + + // Field D32.11 is optional + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_CLASS_PROB) ) + { + result.class_probability = klv::klv_read_int< int >( ptr, (size_t)1 ); + } + + // Fields D32.12-D32.15 are conditional and always sent together + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_SLANT_RANGE) ) + { + result.measurement_uncert = stanag_4607_target_measure_uncert_format{} + .read( ptr ); + } + + // Fields D32.16-D32.17 are conditional and always sent together + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_TRUTH_TAG_APPL) ) + { + result.truth_tag = stanag_4607_truth_tag_format{}.read( ptr ); + } + + // Field D32.18 is optional + if( existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_RADAR_CROSS_SECT) ) + { + result.radar_cross_sect = klv::klv_read_int< int >( ptr, (size_t)1 ); + } + + return result; +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_dwell_segment const& value ) +{ + os << "{ " + << "Existence Mask: { "; + for( stanag_4607_dwell_existence_mask_bit m : value.existence_mask ) + { + os << m << ", "; + } + os << " }, "; + + os << "Revisit Index: " << value.revisit_index << ", " + << "Dwell Index: " << value.dwell_index << ", " + << "Last Dwell of Revisit: " + << ( value.last_dwell_of_revisit + ? "No additional dwells" + : "Additional dwells" ) + << ", " + << "Target Report Count: " << value.target_report_count << ", " + << "Dwell Time: " << value.dwell_time << " ms" << ", " + << "Sensor Position: " << value.sensor_position << ", "; + if( value.scale_factor ) + { + os << "Scale Factor: " << *value.scale_factor << ", "; + } + + if( value.sensor_pos_uncert ) + { + os << "Sensor Position Uncertainty: " << *value.sensor_pos_uncert << ", "; + } + + if( value.sensor_track ) + { + os << "Sensor Track: " << *value.sensor_track << " degrees" << ", " + << "Sensor Speed: " << *value.sensor_speed << " mm/sec" << ", " + << "Sensor Vertical Velocity: " << *value.sensor_vertical_vel + << " dm/sec" << ", "; + } + + if( value.sensor_track_uncert ) + { + os << "Sensor Track Uncertainty: " << *value.sensor_track_uncert + << " degrees" << ", " + << "Sensor Speed Uncertainty: " << *value.sensor_speed_uncert + << " mm/sec" << ", " + << "Sensor Vertical Velocity Uncertainty: " + << *value.sensor_vertical_vel_uncert << " cm/sec" << ", "; + } + + if( value.platform_orient ) + { + os << "Platform Orientation: " << *value.platform_orient << ", "; + } + + os << "Dwell Area: " << value.dwell_area << ", "; + + if( value.sensor_orientation ) + { + os << "Sensor Orientation: " << *value.sensor_orientation << ", "; + } + + if( value.min_detectable_vel ) + { + os << "Minimum Detectable Velocity: " << *value.min_detectable_vel + << " dm/sec" << ", "; + } + + os << "Target Reports: " << value.target_reports + << " }"; + + return os; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP( + stanag_4607_dwell_segment, + &stanag_4607_dwell_segment::existence_mask, + &stanag_4607_dwell_segment::revisit_index, + &stanag_4607_dwell_segment::dwell_index, + &stanag_4607_dwell_segment::last_dwell_of_revisit, + &stanag_4607_dwell_segment::target_report_count, + &stanag_4607_dwell_segment::dwell_time, + &stanag_4607_dwell_segment::sensor_position, + &stanag_4607_dwell_segment::scale_factor, + &stanag_4607_dwell_segment::sensor_pos_uncert, + &stanag_4607_dwell_segment::sensor_track, + &stanag_4607_dwell_segment::sensor_speed, + &stanag_4607_dwell_segment::sensor_vertical_vel, + &stanag_4607_dwell_segment::sensor_track_uncert, + &stanag_4607_dwell_segment::sensor_speed_uncert, + &stanag_4607_dwell_segment::sensor_vertical_vel_uncert, + &stanag_4607_dwell_segment::platform_orient, + &stanag_4607_dwell_segment::dwell_area, + &stanag_4607_dwell_segment::sensor_orientation, + &stanag_4607_dwell_segment::min_detectable_vel, + &stanag_4607_dwell_segment::target_reports +) + +// ---------------------------------------------------------------------------- +stanag_4607_dwell_segment_format +::stanag_4607_dwell_segment_format() +{} + +// ---------------------------------------------------------------------------- +stanag_4607_dwell_segment +stanag_4607_dwell_segment_format +::read( ptr_t& ptr ) const +{ + stanag_4607_dwell_segment result {}; + + // Fields D1-D9 are mandatory + auto mask = klv::klv_read_int< uint64_t >( ptr, (size_t)8 ); + mask >>= 16; + result.existence_mask = klv::bitfield_to_enums< + stanag_4607_dwell_existence_mask_bit, uint64_t >( mask ); + + result.revisit_index = klv::klv_read_int< int >( ptr, (size_t)2 ); + + result.dwell_index = klv::klv_read_int< int >( ptr, (size_t)2 ); + + result.last_dwell_of_revisit = klv::klv_read_int< int >( ptr, (size_t)1 ); + + result.target_report_count = klv::klv_read_int< int >( ptr, (size_t)2 ); + + result.dwell_time = klv::klv_read_int< int >( ptr, (size_t)4 ); + + result.sensor_position.latitude = klv::klv_read_flint< int32_t >({-90, 90}, + ptr, (size_t)4); + result.sensor_position.longitude =klv::klv_read_flint< uint32_t >( + {0, 359.999999916}, ptr, (size_t)4); + result.sensor_position.altitude = klv::klv_read_int< int >( ptr, (size_t)4 ); + + // Fields D10-11 are conditional and always sent together + // Condition: Sent if D32.4 and D32.5 are sent + if( result.existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_SCALE_FACT_LAT) ) + { + result.scale_factor = stanag_4607_scale_factor_format{}.read(ptr); + } + + // Fields D12-D14 are optional and always sent together + if( result.existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_ALONG_TRACK) ) + { + result.sensor_pos_uncert = stanag_4607_sensor_pos_uncert_format{} + .read(ptr); + } + + // Fields D15-D17 are conditional and always sent together + // Condition: Sent when the sensor system provides these parameters + if( result.existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK) ) + { + result.sensor_track = klv::klv_read_flint< uint16_t >({0, 359.9945}, + ptr, 2); + result.sensor_speed = klv::klv_read_int< int >( ptr, (size_t)4 ); + result.sensor_vertical_vel = klv::klv_read_int< int >( ptr, (size_t)1 ); + } + + // Fields D18-D20 are optional and always sent together + if( result.existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK_UNCERT) ) + { + result.sensor_track_uncert = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.sensor_speed_uncert = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.sensor_vertical_vel_uncert = klv::klv_read_int< int >( ptr, + (size_t)2 ); + } + + // Fields D21-D23 are conditional and always sent together + // Condition: Sent when the sensor system provides these parameters + if( result.existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_OREINT_HEADING) ) + { + result.platform_orient = stanag_4607_orientation_format{}.read(ptr); + } + + // Fields D24-27 are mandatory + result.dwell_area.center_lat = klv::klv_read_flint< int32_t >({-90, 90}, + ptr, 4); + result.dwell_area.center_long = klv::klv_read_flint< uint32_t >( + {0, 359.999979}, ptr, 4); + + kwiver::vital::interval interval = {0, 255.9928}; + size_t length = 2; + auto v = klv::klv_read_int< int16_t >(ptr, length); + auto const scale = interval.span() / + (( 0x80ull << ( ( length - 1 ) * 8 ) ) - 1); + + result.dwell_area.range_half_ext = v * scale + interval.lower(); + + result.dwell_area.dwell_angle_half_ext = klv::klv_read_flint< uint16_t >( + {0, 359.9945}, ptr, 2); + + // Fields D28-D30 are optional + // If at least one is sent, any omitted fields are set to 0 + if( result.existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_OREINT_HEADING) or + result.existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_OREINT_PITCH) or + result.existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_ORIENT_ROLL) ) + { + result.sensor_orientation = stanag_4607_orientation_format{}.read(ptr); + } + + // Field D31 is optional + if( result.existence_mask.count( + STANAG_4607_DWELL_EXIST_MASK_BIT_MIN_DETECT_VEL) ) + { + result.min_detectable_vel = klv::klv_read_int< int >( ptr, (size_t)1 ); + } + + // Target reports + std::vector < stanag_4607_target_report > target_reports; + for(int i=0; i +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +namespace kv = kwiver::vital; + + +// ---------------------------------------------------------------------------- +/// Position of the sensor at the temporal center of the dwell +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_sensor_position +{ + double latitude; + double longitude; + int altitude; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_sensor_position const& value ); + + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_sensor_position ) + +// ---------------------------------------------------------------------------- +/// A factor which modifies the value of the reported targetposition (lat, lon) +/// when it is necessary to send the reduced bandwidth version of the Target +/// Report. +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_scale_factor +{ + int lat_scale; + int long_scale; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_scale_factor const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_scale_factor ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_scale_factor_format +{ +public: + stanag_4607_scale_factor_format() {} + + stanag_4607_scale_factor + read( ptr_t& ptr ) const; +}; + + +// ---------------------------------------------------------------------------- +/// Estimate of the standard deviation in the estimated sensor location at +/// the time of the dwell. Expressed in centimeters. +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_sensor_pos_uncert +{ + int along_track; + int cross_track; + int altitude; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_sensor_pos_uncert const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_sensor_pos_uncert ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_sensor_pos_uncert_format +{ +public: + stanag_4607_sensor_pos_uncert_format() {} + + stanag_4607_sensor_pos_uncert + read( ptr_t& ptr ) const; +}; + + +// ---------------------------------------------------------------------------- +/// The toll angle of the platform at the time of the dwell. +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_orientation +{ + double heading; + double pitch; + double roll; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_orientation const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_orientation ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_orientation_format +{ +public: + stanag_4607_orientation_format() {} + + stanag_4607_orientation + read( ptr_t& ptr ) const; +}; + + +// ---------------------------------------------------------------------------- +/// The position of the center of the dwell area +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_area +{ + double center_lat; + double center_long; + double range_half_ext; + double dwell_angle_half_ext; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_dwell_area const& value ); + + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_dwell_area ) + +// ---------------------------------------------------------------------------- +/// Classification of the target. +enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_classification +{ + STANAG_4607_TARGET_CLASS_NO_INFO_LIVE, + STANAG_4607_TARGET_CLASS_TRACKED_VEHICLE_LIVE, + STANAG_4607_TARGET_CLASS_WHEELED_VEHICLE_LIVE, + STANAG_4607_TARGET_CLASS_ROTARY_WING_AIRCRAFT_LIVE, + STANAG_4607_TARGET_CLASS_FIXED_WING_AIRCRAFT_LIVE, + STANAG_4607_TARGET_CLASS_STATIONARY_ROTATOR_LIVE, + STANAG_4607_TARGET_CLASS_MARITIME_LIVE, + STANAG_4607_TARGET_CLASS_BEACON_LIVE, + STANAG_4607_TARGET_CLASS_AMPHIBIOUS_LIVE, + STANAG_4607_TARGET_CLASS_PERSON_LIVE, + STANAG_4607_TARGET_CLASS_VEHICLE_LIVE, + STANAG_4607_TARGET_CLASS_ANIMAL_LIVE, + STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_LIVE_LAND, + STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_LIVE_MARITIME, + // Note: 14-125 are reserved + STANAG_4607_TARGET_CLASS_OTHER_LIVE = 126, + STANAG_4607_TARGET_CLASS_UNKNOWN_LIVE, + STANAG_4607_TARGET_CLASS_NO_INFO_SIM, + STANAG_4607_TARGET_CLASS_TRACKED_VEHICLE_SIM, + STANAG_4607_TARGET_CLASS_WHEELED_VEHICLE_SIM, + STANAG_4607_TARGET_CLASS_ROTARY_WING_AIRCRAFT_SIM, + STANAG_4607_TARGET_CLASS_FIXED_WING_AIRCRAFT_SIM, + STANAG_4607_TARGET_CLASS_STATIONARY_ROTATOR_SIM, + STANAG_4607_TARGET_CLASS_MARITIME_SIM, + STANAG_4607_TARGET_CLASS_BEACON_SIM, + STANAG_4607_TARGET_CLASS_AMPHIBIOUS_SIM, + STANAG_4607_TARGET_CLASS_PERSON_SIM, + STANAG_4607_TARGET_CLASS_VEHICLE_SIM, + STANAG_4607_TARGET_CLASS_ANIMAL_SIM, + STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_SIM_LAND, + STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_SIM_MARITIME, + STANAG_4607_TARGET_CLASS_TAGGING_DEVICE, + // Note: 143-253 are reserved + STANAG_4607_TARGET_CLASS_OTHER_SIM = 254, + STANAG_4607_TARGET_CLASS_UNKNOWN_SIM, + STANAG_4607_TARGET_CLASS_ENUM_END, +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + stanag_4607_target_classification const& value ); + +// ---------------------------------------------------------------------------- +/// Standard deviation of the target measurements. +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_measure_uncert +{ + int slant_range; + int cross_range; + int height; + int radial_velocity; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_target_measure_uncert const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_target_measure_uncert ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_measure_uncert_format +{ +public: + stanag_4607_target_measure_uncert_format() {} + + stanag_4607_target_measure_uncert + read( ptr_t& ptr ) const; +}; + + +// ---------------------------------------------------------------------------- +/// Information used to generate the MTI Target. +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_truth_tag +{ + int application; + int entity; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_truth_tag const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_truth_tag ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_truth_tag_format +{ +public: + stanag_4607_truth_tag_format() {} + + stanag_4607_truth_tag + read( ptr_t& ptr ) const; +}; + + +// ---------------------------------------------------------------------------- +/// Each bit of the Existence Mask indicates whether or not the corresponding +/// field of the Dwell Segment is present in the data stream. +enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_existence_mask_bit +{ + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_RADAR_CROSS_SECT, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_TRUTH_TAG_ENTITY, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_TRUTH_TAG_APPL, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_RADIAL_VEL, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_HEIGHT, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_CROSS_RNAGE, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_SLANT_RANGE, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_CLASS_PROB, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_CLASS, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_SNR, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_WRAP_VEL, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_VEL_LOS, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_GEODETIC_HEIGHT, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_DELTA_LONG, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_DELTA_LAT, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_HI_RES_LONG, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_HI_RES_LAT, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_MTI_REPORT_IDX, + STANAG_4607_DWELL_EXIST_MASK_BIT_MIN_DETECT_VEL, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_ORIENT_ROLL, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_OREINT_PITCH, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_OREINT_HEADING, + STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_DWELL_ANGLE_HALF, + STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_RANGE_HALF, + STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_CENTER_LONG, + STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_CENTER_LAT, + STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_OREINT_ROLL, + STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_ORIENT_PITCH, + STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_OREINT_HEADING, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_VERTICAL_VEL_UNCERT, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_SPEED_UNCERT, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK_UNCERT, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_VERTICAL_VEL, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_SPEED, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_ALT, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_CROSS_TRACK, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_ALONG_TRACK, + STANAG_4607_DWELL_EXIST_MASK_BIT_SCALE_FACT_LONG, + STANAG_4607_DWELL_EXIST_MASK_BIT_SCALE_FACT_LAT, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_ALT, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_LONG, + STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_LAT, + STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_TIME, + STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_COUNT, + STANAG_4607_DWELL_EXIST_MASK_BIT_LAST_DWELL_REVISIT, + STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_INDEX, + STANAG_4607_DWELL_EXIST_MASK_BIT_REVISIT_INDEX, +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + stanag_4607_dwell_existence_mask_bit const& value ); + +// ---------------------------------------------------------------------------- +/// The position of the reported detection. +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_location +{ + kv::optional< double > hi_res_lat; + kv::optional< double > hi_res_long; + kv::optional< int > delta_lat; + kv::optional< int > delta_long; + kv::optional< int > geodetic_height; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_target_location const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_target_location ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_location_format +{ +public: + stanag_4607_target_location_format() {} + + stanag_4607_target_location + read( ptr_t& ptr, + std::set< stanag_4607_dwell_existence_mask_bit > existence_mask ) const; +}; + + +// ---------------------------------------------------------------------------- +/// Each target observed within the dwell. +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_report +{ + kv::optional< int > mti_report_idx; + kv::optional< stanag_4607_target_location > location; + kv::optional< int > velocity_los; + kv::optional< int > wrap_velocity; + kv::optional< int > snr; + kv::optional< stanag_4607_target_classification > classification; + kv::optional< int > class_probability; + kv::optional< stanag_4607_target_measure_uncert > measurement_uncert; + kv::optional< stanag_4607_truth_tag > truth_tag; + kv::optional< int > radar_cross_sect; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_target_report const& value ); + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + std::vector< stanag_4607_target_report > const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_target_report ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_report_format +{ +public: + stanag_4607_target_report_format(); + + stanag_4607_target_report + read( ptr_t& ptr, + std::set< stanag_4607_dwell_existence_mask_bit > existence_mask ) const; +}; + + +// ---------------------------------------------------------------------------- +/// A report on a grouping of zero or more target reports. +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_segment +{ + std::set< stanag_4607_dwell_existence_mask_bit > existence_mask; + int revisit_index; + int dwell_index; + int last_dwell_of_revisit; + int target_report_count; + int dwell_time; + stanag_4607_sensor_position sensor_position; + kv::optional< stanag_4607_scale_factor > scale_factor; + kv::optional< stanag_4607_sensor_pos_uncert > sensor_pos_uncert; + kv::optional< double > sensor_track; + kv::optional< int > sensor_speed; + kv::optional< int > sensor_vertical_vel; + kv::optional< int > sensor_track_uncert; + kv::optional< int > sensor_speed_uncert; + kv::optional< int > sensor_vertical_vel_uncert; + kv::optional< stanag_4607_orientation > platform_orient; + stanag_4607_dwell_area dwell_area; + kv::optional< stanag_4607_orientation > sensor_orientation; + kv::optional< int > min_detectable_vel; + std::vector< stanag_4607_target_report > target_reports; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_dwell_segment const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_dwell_segment ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_segment_format + : public stanag_4607_segment_data_format_< stanag_4607_dwell_segment > +{ +public: + stanag_4607_dwell_segment_format(); + + + size_t size; + + stanag_4607_dwell_segment + read( ptr_t& ptr ) const; +}; + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver + +#endif diff --git a/arrows/stanag/stanag_4607_segments.cxx b/arrows/stanag/segments/stanag_4607_mission_segment.cxx similarity index 54% rename from arrows/stanag/stanag_4607_segments.cxx rename to arrows/stanag/segments/stanag_4607_mission_segment.cxx index 638e1c6dae..38cd18b13c 100644 --- a/arrows/stanag/stanag_4607_segments.cxx +++ b/arrows/stanag/segments/stanag_4607_mission_segment.cxx @@ -2,7 +2,7 @@ // OSI-approved BSD 3-Clause License. See top-level LICENSE file or // https://github.com/Kitware/kwiver/blob/master/LICENSE for details. -#include "stanag_4607_segments.h" +#include "stanag_4607_mission_segment.h" namespace ka = kwiver::arrows; @@ -18,238 +18,6 @@ namespace arrows { namespace stanag { -// ---------------------------------------------------------------------------- -stanag_4607_segment_type_traits_lookup const& -stanag_4607_segment_type_traits_lookup_table() -{ - static stanag_4607_segment_type_traits_lookup const lookup = { - { - STANAG_4607_SEGMENT_TYPE_MISSION, "STANAG_4607_SEGMENT_TYPE_MISSION", - std::make_shared< stanag_4607_mission_segment_format >(), - "Mission Segment" - } - }; - - // TODO finish rest of segments - /* - { - STANAG_4607_SEGMENT_TYPE_DWELL, - std::make_shared<>(), - "Dwell Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_HRR, - std::make_shared<>(), - "HRR Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_JOB_DEFINITION, - std::make_shared<>(), - "Job Definition Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_FREE_TEXT, - std::make_shared<>(), - "Free Text Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_LOW_REFLECTIVITY_INDEX, - std::make_shared<>(), - "Low Reflectivity Index Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_GROUP, - std::make_shared<>(), - "Group Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_ATTACHED_TARGET, - std::make_shared<>(), - "Attached Target Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_TEST_AND_STATUS, - std::make_shared<>(), - "Test and Status Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_SYSTEM_SPECIFIC, - std::make_shared<>(), - "System-Specific Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_PROCESSING_HISTORY, - std::make_shared<>(), - "Processing History Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_PLATFORM_LOCATION, - std::make_shared<>(), - "Platform Location Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_JOB_REQUEST, - std::make_shared<>(), - "Job Request Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_JOB_ACKNOWLEDGE, - std::make_shared<>(), - "Job Acknowledge Segment" - }, - { - STANAG_4607_SEGMENT_TYPE_ENUM_END, - std::make_shared<>(), - "Unknown STANAG4607 segment type" - } */ - //}; - - return lookup; -} - -// ---------------------------------------------------------------------------- -std::ostream& -operator<<( std::ostream& os, - stanag_4607_segment_type const& value ) -{ - os << stanag_4607_segment_type_traits_lookup_table().by_type( value ) - .name(); - - return os; -} - -// ---------------------------------------------------------------------------- -std::ostream& -operator<<( std::ostream& os, stanag_4607_segment_header const& value ) -{ - os << "{ " - << "Segment Type: " << value.segment_type << ", " - << "Segment Size: " << value.segment_size - << " }"; - - return os; -} - -// ---------------------------------------------------------------------------- -DEFINE_STANAG_STRUCT_CMP( - stanag_4607_segment_header, - &stanag_4607_segment_header::segment_type, - &stanag_4607_segment_header::segment_size -) - -// ---------------------------------------------------------------------------- -stanag_4607_segment_header_format -::stanag_4607_segment_header_format() -{} - -// ---------------------------------------------------------------------------- -stanag_4607_segment_header -stanag_4607_segment_header_format -::read( ptr_t& ptr ) const -{ - stanag_4607_segment_header result; - - result.segment_type = static_cast< stanag_4607_segment_type >( - ka::klv::klv_read_int< uint64_t >( ptr, 1 )); - result.segment_size = ka::klv::klv_read_int< size_t >( ptr, 4 ); - - return result; -} - -// ---------------------------------------------------------------------------- -stanag_4607_segment_type_traits_lookup -::stanag_4607_segment_type_traits_lookup( - std::initializer_list< stanag_4607_segment_type_traits > const& traits ) - : m_traits{ traits.begin(), traits.end() } -{ - initialize(); -} - -// ---------------------------------------------------------------------------- -stanag_4607_segment_type_traits_lookup -::stanag_4607_segment_type_traits_lookup( - std::vector< stanag_4607_segment_type_traits > const& traits ) - : m_traits{ traits.begin(), traits.end() } -{ - initialize(); -} - -// ---------------------------------------------------------------------------- -stanag_4607_segment_type_traits const& -stanag_4607_segment_type_traits_lookup -::by_type( uint16_t type ) const -{ - auto const result = m_type_to_traits.find( type ); - return ( result == m_type_to_traits.end() ) - ? m_traits.at( 0 ) - : *result->second; -} - -// ---------------------------------------------------------------------------- -stanag_4607_segment_type_traits const& -stanag_4607_segment_type_traits_lookup -::by_enum_name( std::string const& enum_name ) const -{ - auto const result = m_enum_name_to_traits.find( enum_name ); - return ( result == m_enum_name_to_traits.end() ) - ? m_traits.at( 0 ) - : *result->second; -} - -// ---------------------------------------------------------------------------- -void -stanag_4607_segment_type_traits_lookup -::initialize() -{ - if( m_traits.empty() ) - { - throw std::logic_error( "traits cannot be empty" ); - } - - for( auto const& trait : m_traits ) - { - if( trait.type() ) - { - m_type_to_traits.emplace( trait.type(), &trait ).second; - } - - if( !trait.enum_name().empty() ) - { - m_enum_name_to_traits.emplace( trait.enum_name(), &trait ).second; - } - } -} - -// ---------------------------------------------------------------------------- -stanag_4607_mission_segment_format -::stanag_4607_mission_segment_format() -{} - -// ---------------------------------------------------------------------------- -stanag_4607_mission_segment -stanag_4607_mission_segment_format -::read( ptr_t& ptr ) const -{ - stanag_4607_mission_segment result; - - result.mission_plan = trim_whitespace( klv::klv_read_string( ptr, - (size_t)12 ) ); - - result.flight_plan = trim_whitespace( klv::klv_read_string( ptr, - (size_t)12 ) ); - - result.platform_type = static_cast< stanag_4607_mission_segment_platform >( - klv::klv_read_int< uint64_t >( ptr, (size_t)1 )); - - result.platform_configuration = trim_whitespace( klv::klv_read_string( - ptr, (size_t)10 ) ); - - result.reference_time.year = klv::klv_read_int< int >( ptr, (size_t)2 ); - result.reference_time.month = klv::klv_read_int< int >( ptr, (size_t)1 ); - result.reference_time.day = klv::klv_read_int< int >( ptr, (size_t)1 ); - - return result; -} // ---------------------------------------------------------------------------- std::ostream& @@ -356,6 +124,36 @@ DEFINE_STANAG_STRUCT_CMP( &stanag_4607_mission_segment::reference_time ) +// ---------------------------------------------------------------------------- +stanag_4607_mission_segment_format +::stanag_4607_mission_segment_format() +{} + +// ---------------------------------------------------------------------------- +stanag_4607_mission_segment +stanag_4607_mission_segment_format +::read( ptr_t& ptr ) const +{ + stanag_4607_mission_segment result; + + result.mission_plan = trim_whitespace( klv::klv_read_string( ptr, + (size_t)12 ) ); + + result.flight_plan = trim_whitespace( klv::klv_read_string( ptr, + (size_t)12 ) ); + + result.platform_type = static_cast< stanag_4607_mission_segment_platform >( + klv::klv_read_int< uint64_t >( ptr, (size_t)1 )); + + result.platform_configuration = trim_whitespace( klv::klv_read_string( + ptr, (size_t)10 ) ); + + result.reference_time.year = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.reference_time.month = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.reference_time.day = klv::klv_read_int< int >( ptr, (size_t)1 ); + + return result; +} } // namespace stanag diff --git a/arrows/stanag/segments/stanag_4607_mission_segment.h b/arrows/stanag/segments/stanag_4607_mission_segment.h new file mode 100644 index 0000000000..bd4bf6a9d7 --- /dev/null +++ b/arrows/stanag/segments/stanag_4607_mission_segment.h @@ -0,0 +1,140 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +/// \file +/// Defines a STANAG 4607 segment header and the various segment types + +#ifndef KWIVER_ARROWS_STANAG_4607_MISSION_SEGMENT_H_ +#define KWIVER_ARROWS_STANAG_4607_MISSION_SEGMENT_H_ + +#include "stanag_4607_segments.h" +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +namespace kv = kwiver::vital; + +// ---------------------------------------------------------------------------- +/// Identifies the type of platform that originated the data +enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment_platform +{ + STANAG_4607_MISSION_PLATFORM_UNIDENTIFIED, + STANAG_4607_MISSION_PLATFORM_ACS, + STANAG_4607_MISSION_PLATFORM_ARL_M, + STANAG_4607_MISSION_PLATFORM_SENTINEL, + STANAG_4607_MISSION_PLATFORM_ROTARY_WING_RADAR, + STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_NAVY, + STANAG_4607_MISSION_PLATFORM_HORIZON, + STANAG_4607_MISSION_PLATFORM_E_8, + STANAG_4607_MISSION_PLATFORM_P_3C, + STANAG_4607_MISSION_PLATFORM_PREDATOR, + STANAG_4607_MISSION_PLATFORM_RADARSAT2, + STANAG_4607_MISSION_PLATFORM_U_2, + STANAG_4607_MISSION_PLATFORM_E_10, + STANAG_4607_MISSION_PLATFORM_UGS_SINGLE, + STANAG_4607_MISSION_PLATFORM_UGS_CLUSTER, + STANAG_4607_MISSION_PLATFORM_GROUND_BASED, + STANAG_4607_MISSION_PLATFORM_UAV_MARINES, + STANAG_4607_MISSION_PLATFORM_UAV_NAVY, + STANAG_4607_MISSION_PLATFORM_UAV_AIR_FORCE, + STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AIR_FORCE, + STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AUSTRALIA, + STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_GERMANY, + STANAG_4607_MISSION_PLATFORM_PAUL_REVERE, + STANAG_4607_MISSION_PLATFORM_MARINER_UAV, + STANAG_4607_MISSION_PLATFORM_BAC_11, + STANAG_4607_MISSION_PLATFORM_COYOTE, + STANAG_4607_MISSION_PLATFORM_KING_AIR, + STANAG_4607_MISSION_PLATFORM_LIMIT, + STANAG_4607_MISSION_PLATFORM_NRL_NP_3B, + STANAG_4607_MISSION_PLATFORM_SOSTAR_X, + STANAG_4607_MISSION_PLATFORM_WATCHKEEPER, + STANAG_4607_MISSION_PLATFORM_ALLIANCE_GROUND_SURVEILLANCE, + STANAG_4607_MISSION_PLATFORM_STRYKER, + STANAG_4607_MISSION_PLATFORM_AGS, + STANAG_4607_MISSION_PLATFORM_SIDM, + STANAG_4607_MISSION_PLATFORM_REAPER, + STANAG_4607_MISSION_PLATFORM_WARRIOR_A, + STANAG_4607_MISSION_PLATFORM_WARRIOR, + STANAG_4607_MISSION_PLATFORM_TWIN_OTTER, + // Note: 40-254 are available for future use + STANAG_4607_MISSION_PLATFORM_OTHER = 255, + STANAG_4607_MISSION_PLATFORM_ENUM_END, +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + stanag_4607_mission_segment_platform const& value ); + +// ---------------------------------------------------------------------------- +/// UTC time in which the mission originated +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_reference_time +{ + int year; + int month; + int day; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + stanag_4607_mission_reference_time const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_mission_reference_time ) + +// ---------------------------------------------------------------------------- +/// Information concerning the mission +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment +{ + std::string mission_plan; + std::string flight_plan; + stanag_4607_mission_segment_platform platform_type; + std::string platform_configuration; + stanag_4607_mission_reference_time reference_time; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_mission_segment const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_mission_segment ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment_format + : public stanag_4607_segment_data_format_< stanag_4607_mission_segment > +{ +public: + stanag_4607_mission_segment_format(); + + using data_type = stanag_4607_mission_segment; + + stanag_4607_mission_segment + read( ptr_t& ptr ) const; +}; + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver + +#endif diff --git a/arrows/stanag/segments/stanag_4607_segment_lookup.cxx b/arrows/stanag/segments/stanag_4607_segment_lookup.cxx new file mode 100644 index 0000000000..60accd1da5 --- /dev/null +++ b/arrows/stanag/segments/stanag_4607_segment_lookup.cxx @@ -0,0 +1,206 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_4607_segment_lookup.h" + +namespace ka = kwiver::arrows; + +#include + +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits_lookup const& +stanag_4607_segment_type_traits_lookup_table() +{ + static stanag_4607_segment_type_traits_lookup const lookup = { + { + STANAG_4607_SEGMENT_TYPE_MISSION, + "STANAG_4607_SEGMENT_TYPE_MISSION", + std::make_shared< stanag_4607_mission_segment_format >(), + "Mission Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_DWELL, + "STANAG_4607_SEGMENT_TYPE_DWELL", + std::make_shared< stanag_4607_dwell_segment_format >(), + "Dwell Segment" + } + + // Currently supports a subset of the standard. More segments + // will be added in the future. + /* + { + STANAG_4607_SEGMENT_TYPE_HRR, + "STANAG_4607_SEGMENT_TYPE_HRR", + std::make_shared<>(), + "HRR Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_JOB_DEFINITION, + "STANAG_4607_SEGMENT_TYPE_JOB_DEFINITION", + std::make_shared<>(), + "Job Definition Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_FREE_TEXT, + "STANAG_4607_SEGMENT_TYPE_FREE_TEXT", + std::make_shared<>(), + "Free Text Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_LOW_REFLECTIVITY_INDEX, + "STANAG_4607_SEGMENT_TYPE_LOW_REFLECTIVITY_INDEX", + std::make_shared<>(), + "Low Reflectivity Index Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_GROUP, + "STANAG_4607_SEGMENT_TYPE_GROUP", + std::make_shared<>(), + "Group Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_ATTACHED_TARGET, + "STANAG_4607_SEGMENT_TYPE_ATTACHED_TARGET", + std::make_shared<>(), + "Attached Target Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_TEST_AND_STATUS, + "STANAG_4607_SEGMENT_TYPE_TEST_AND_STATUS", + std::make_shared<>(), + "Test and Status Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_SYSTEM_SPECIFIC, + "STANAG_4607_SEGMENT_TYPE_SYSTEM_SPECIFIC", + std::make_shared<>(), + "System-Specific Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_PROCESSING_HISTORY, + "STANAG_4607_SEGMENT_TYPE_PROCESSING_HISTORY", + std::make_shared<>(), + "Processing History Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_PLATFORM_LOCATION, + "STANAG_4607_SEGMENT_TYPE_PLATFORM_LOCATION", + std::make_shared<>(), + "Platform Location Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_JOB_REQUEST, + "STANAG_4607_SEGMENT_TYPE_JOB_REQUEST", + std::make_shared<>(), + "Job Request Segment" + }, + { + STANAG_4607_SEGMENT_TYPE_JOB_ACKNOWLEDGE, + "STANAG_4607_SEGMENT_TYPE_JOB_ACKNOWLEDGE", + std::make_shared<>(), + "Job Acknowledge Segment" + },*/ + /*{ + STANAG_4607_SEGMENT_TYPE_ENUM_END, + "STANAG_4607_SEGMENT_TYPE_ENUM_END", + std::make_shared< void >(), + "Unknown STANAG4607 segment type" + } */ + }; + + return lookup; +} + + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits_lookup +::stanag_4607_segment_type_traits_lookup( + std::initializer_list< stanag_4607_segment_type_traits > const& traits ) + : m_traits{ traits.begin(), traits.end() } +{ + initialize(); +} + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits_lookup +::stanag_4607_segment_type_traits_lookup( + std::vector< stanag_4607_segment_type_traits > const& traits ) + : m_traits{ traits.begin(), traits.end() } +{ + initialize(); +} + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits const& +stanag_4607_segment_type_traits_lookup +::by_type( uint16_t type ) const +{ + auto const result = m_type_to_traits.find( type ); + return ( result == m_type_to_traits.end() ) + ? m_traits.at( 0 ) + : *result->second; +} + +// ---------------------------------------------------------------------------- +stanag_4607_segment_type_traits const& +stanag_4607_segment_type_traits_lookup +::by_enum_name( std::string const& enum_name ) const +{ + auto const result = m_enum_name_to_traits.find( enum_name ); + return ( result == m_enum_name_to_traits.end() ) + ? m_traits.at( 0 ) + : *result->second; +} + +// ---------------------------------------------------------------------------- +void +stanag_4607_segment_type_traits_lookup +::initialize() +{ + if( m_traits.empty() ) + { + throw std::logic_error( "traits cannot be empty" ); + } + + for( auto const& trait : m_traits ) + { + if( trait.type() ) + { + m_type_to_traits.emplace( trait.type(), &trait ).second; + } + + if( !trait.enum_name().empty() ) + { + m_enum_name_to_traits.emplace( trait.enum_name(), &trait ).second; + } + } +} + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, + stanag_4607_segment_type const& value ) +{ + os << stanag_4607_segment_type_traits_lookup_table().by_type( value ) + .name(); + + return os; +} + + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver diff --git a/arrows/stanag/segments/stanag_4607_segment_lookup.h b/arrows/stanag/segments/stanag_4607_segment_lookup.h new file mode 100644 index 0000000000..ac368e09e0 --- /dev/null +++ b/arrows/stanag/segments/stanag_4607_segment_lookup.h @@ -0,0 +1,123 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +/// \file +/// Defines a STANAG 4607 segment header and the various segment types + +#ifndef KWIVER_ARROWS_STANAG_4607_SEGMENT_LOOKUP_H_ +#define KWIVER_ARROWS_STANAG_4607_SEGMENT_LOOKUP_H_ + +#include + +#include "stanag_4607_dwell_segment.h" +#include "stanag_4607_mission_segment.h" + +#include +#include +#include +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +namespace kv = kwiver::vital; + +// ---------------------------------------------------------------------------- +/// The type, enumeration, and name of a segment +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_type_traits +{ +public: + stanag_4607_segment_type_traits( uint16_t type, + std::string const& enum_name, + stanag_4607_segment_data_format_sptr format, + std::string const& name ) + : m_type{ type }, m_enum_name{ enum_name }, m_format{ format }, + m_name{ name } + {} + + /// Returns the enumeration value of the segment + uint16_t + type() const { return m_type; } + + /// Return a string version of the segment enumeration + std::string + enum_name() const { return m_enum_name; } + + /// Return the data format used to represent this segment's value. + stanag_4607_segment_data_format& + format() const { return *m_format; } + + /// Return the segment's name. + std::string + name() const { return m_name; } + +private: + uint16_t m_type; + std::string m_enum_name; + stanag_4607_segment_data_format_sptr m_format; + std::string m_name; +}; + +// ---------------------------------------------------------------------------- +/// Lookup table used to match a segment to its traits +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_type_traits_lookup +{ +public: + using iterator = + typename std::vector< stanag_4607_segment_type_traits >::const_iterator; + using init_list = + typename std::initializer_list< stanag_4607_segment_type_traits >; + + stanag_4607_segment_type_traits_lookup( + std::initializer_list< stanag_4607_segment_type_traits > const& traits ); + + stanag_4607_segment_type_traits_lookup( + std::vector< stanag_4607_segment_type_traits > const& traits ); + + iterator + begin() const { return m_traits.begin(); } + + iterator + end() const { return m_traits.end(); } + + stanag_4607_segment_type_traits const& + by_type( uint16_t type ) const; + + /// Return the traits object with \p enum_name as its enum name. + stanag_4607_segment_type_traits const& + by_enum_name( std::string const& enum_name ) const; + +private: + void initialize(); + + std::vector< stanag_4607_segment_type_traits > m_traits; + std::map< std::string, + stanag_4607_segment_type_traits const* > m_enum_name_to_traits; + std::map< uint16_t, + stanag_4607_segment_type_traits const* > m_type_to_traits; +}; + +// ---------------------------------------------------------------------------- +/// Return a traits lookup object for segment types. +stanag_4607_segment_type_traits_lookup const& +stanag_4607_segment_type_traits_lookup_table(); + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, + stanag_4607_segment_type const& value ); + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver + +#endif diff --git a/arrows/stanag/segments/stanag_4607_segments.cxx b/arrows/stanag/segments/stanag_4607_segments.cxx new file mode 100644 index 0000000000..d39e016754 --- /dev/null +++ b/arrows/stanag/segments/stanag_4607_segments.cxx @@ -0,0 +1,63 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_4607_segments.h" + +namespace ka = kwiver::arrows; + +#include + +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +// ---------------------------------------------------------------------------- +std::ostream& +operator<<( std::ostream& os, stanag_4607_segment_header const& value ) +{ + os << "{ " + << "Segment Type: " << value.segment_type << ", " + << "Segment Size: " << value.segment_size + << " }"; + + return os; +} + +// ---------------------------------------------------------------------------- +DEFINE_STANAG_STRUCT_CMP( + stanag_4607_segment_header, + &stanag_4607_segment_header::segment_type, + &stanag_4607_segment_header::segment_size +) + +// ---------------------------------------------------------------------------- +stanag_4607_segment_header_format +::stanag_4607_segment_header_format() +{} + +// ---------------------------------------------------------------------------- +stanag_4607_segment_header +stanag_4607_segment_header_format +::read( ptr_t& ptr ) const +{ + stanag_4607_segment_header result; + + result.segment_type = static_cast< stanag_4607_segment_type >( + ka::klv::klv_read_int< uint64_t >( ptr, 1 )); + result.segment_size = ka::klv::klv_read_int< size_t >( ptr, 4 ); + + return result; +} + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver diff --git a/arrows/stanag/segments/stanag_4607_segments.h b/arrows/stanag/segments/stanag_4607_segments.h new file mode 100644 index 0000000000..d9dae20617 --- /dev/null +++ b/arrows/stanag/segments/stanag_4607_segments.h @@ -0,0 +1,136 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +/// \file +/// Defines a STANAG 4607 segment header and the various segment types + +#ifndef KWIVER_ARROWS_STANAG_4607_SEGMENTS_H_ +#define KWIVER_ARROWS_STANAG_4607_SEGMENTS_H_ + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace kwiver { + +namespace arrows { + +namespace stanag { + +namespace kv = kwiver::vital; + +// ---------------------------------------------------------------------------- +/// The type of message contained in the segment +enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_type : uint16_t +{ + STANAG_4607_SEGMENT_TYPE_MISSION = 1, + STANAG_4607_SEGMENT_TYPE_DWELL = 2, + STANAG_4607_SEGMENT_TYPE_HRR = 3, + // Note: 4 is reserved + STANAG_4607_SEGMENT_TYPE_JOB_DEFINITION = 5, + STANAG_4607_SEGMENT_TYPE_FREE_TEXT = 6, + STANAG_4607_SEGMENT_TYPE_LOW_REFLECTIVITY_INDEX = 7, + STANAG_4607_SEGMENT_TYPE_GROUP = 8, + STANAG_4607_SEGMENT_TYPE_ATTACHED_TARGET = 9, + STANAG_4607_SEGMENT_TYPE_TEST_AND_STATUS = 10, + STANAG_4607_SEGMENT_TYPE_SYSTEM_SPECIFIC = 11, + STANAG_4607_SEGMENT_TYPE_PROCESSING_HISTORY = 12, + STANAG_4607_SEGMENT_TYPE_PLATFORM_LOCATION = 13, + // Note: 14-100 are reserved for new segments + STANAG_4607_SEGMENT_TYPE_JOB_REQUEST = 101, + STANAG_4607_SEGMENT_TYPE_JOB_ACKNOWLEDGE = 102, + // Note: 103-127 are reserved for future use + // Note: 128-255 are reserved for extensions + STANAG_4607_SEGMENT_TYPE_ENUM_END = 256, +}; + +// ---------------------------------------------------------------------------- +/// Identifies the type and size of the segment that follows +struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_header +{ + stanag_4607_segment_type segment_type; + size_t segment_size; +}; + +// ---------------------------------------------------------------------------- +KWIVER_ALGO_STANAG_EXPORT +std::ostream& +operator<<( std::ostream& os, stanag_4607_segment_header const& value ); + +// ---------------------------------------------------------------------------- +DECLARE_STANAG_CMP( stanag_4607_segment_header ) + +// ---------------------------------------------------------------------------- +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_header_format + : public stanag_4607_segment_header +{ +public: + stanag_4607_segment_header_format(); + + const size_t size = 5; // Number of bytes in the segment header + + stanag_4607_segment_header + read( ptr_t& ptr ) const; +}; + +// ---------------------------------------------------------------------------- +/// Untyped base for STANAG formats +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_data_format +{ +public: + explicit + stanag_4607_segment_data_format() {} + + virtual + ~stanag_4607_segment_data_format() = default; + + template < class T > T + read( ptr_t& ptr ) const; +}; + +using stanag_4607_segment_data_format_sptr = + std::shared_ptr< stanag_4607_segment_data_format >; + +// ---------------------------------------------------------------------------- +/// Typed base for STANAG formats +template < class T > +class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_data_format_ + : public stanag_4607_segment_data_format +{ +public: + using data_type = T; + + explicit + stanag_4607_segment_data_format_() + {} + + virtual + ~stanag_4607_segment_data_format_() {} + + T + read( ptr_t& ptr ) const; +}; + +template < class T > +T +stanag_4607_segment_data_format +::read( ptr_t& ptr ) const +{ + return dynamic_cast< const stanag_4607_segment_data_format_< T >& >( *this ) + .read( ptr ); +} + +} // namespace stanag + +} // namespace arrows + +} // namespace kwiver + +#endif diff --git a/arrows/stanag/stanag_4607_packet.cxx b/arrows/stanag/stanag_4607_packet.cxx index a7ffedf9b6..2bdfd799c3 100644 --- a/arrows/stanag/stanag_4607_packet.cxx +++ b/arrows/stanag/stanag_4607_packet.cxx @@ -5,6 +5,7 @@ #include "stanag_4607_packet.h" #include +#include namespace kwiver { @@ -189,10 +190,20 @@ operator<<( std::ostream& os, stanag_4607_packet const& value ) } for ( size_t i=0; i const& value ) } for( auto v : value ) { - os << v; + os << v << std::endl; os << std::endl; } return os; @@ -245,8 +256,8 @@ ::read( ptr_t& ptr ) const auto packet_size = packet_header_data.packet_size; std::vector< stanag_4607_segment_header > segment_headers; - // TODO: make this any segment type - std::vector< stanag_4607_mission_segment > segments; + std::vector< stanag_4607_segments > segments; + auto it = segments.begin(); while( bytes_read_in_packet < packet_size ) { @@ -262,8 +273,21 @@ ::read( ptr_t& ptr ) const size_t segment_size = segment_header_data.segment_size; // Read message segment - auto message = format.read( ptr ); - segments.push_back( message ); + stanag_4607_segments message; + if( typeid(format) == typeid(stanag_4607_mission_segment_format) ) + { + message = stanag_4607_mission_segment_format{}.read( ptr ); + } + else if( typeid(format) == typeid(stanag_4607_dwell_segment_format) ) + { + message = stanag_4607_dwell_segment_format{}.read( ptr ); + } + + //std::visit([](const auto &x) + //{ std::cout << x << std::endl; }, message); + + segments.insert(it, message); + it = segments.end(); bytes_read_in_packet += segment_size; } @@ -278,21 +302,20 @@ ::read( ptr_t& ptr ) const // ---------------------------------------------------------------------------- std::vector< stanag_4607_packet > -read_stanag_4607_data( ptr_t& ptr ) +read_stanag_4607_data( std::vector< uint8_t > input_bytes ) { + auto ptr = &*input_bytes.cbegin(); std::vector< stanag_4607_packet > result; + auto it = result.begin(); - // TODO loop over all packets - //while(ptr != &*input_bytes.cend() ) - //{ - stanag_4607_packet_format packet; - stanag_4607_packet packet_data = packet.read( ptr ); - result.push_back( packet_data ); - - //} - - //std::vector< stanag_4607_packet > result{ packet_data }; + while( ptr != &*input_bytes.cend() ) + { + stanag_4607_packet_format packet; + stanag_4607_packet packet_data = packet.read( ptr ); + result.insert( it, packet_data ); + it = result.end(); + } return result; } diff --git a/arrows/stanag/stanag_4607_packet.h b/arrows/stanag/stanag_4607_packet.h index b88e632aa6..d2ac9ca60c 100644 --- a/arrows/stanag/stanag_4607_packet.h +++ b/arrows/stanag/stanag_4607_packet.h @@ -5,14 +5,21 @@ /// \file /// Defines a STANAG 4607 packet and packet header +/// STANAG 4607 documentation can be found at: +/// https://nso.nato.int/nso/nsdd/main/standards/stanag-details/8003/EN + #ifndef KWIVER_ARROWS_STANAG_4607_PACKET_H_ #define KWIVER_ARROWS_STANAG_4607_PACKET_H_ #include -#include "stanag_4607_segments.h" #include "stanag_util.h" +#include +#include +#include + +#include namespace ka = kwiver::arrows; #include @@ -27,6 +34,9 @@ namespace arrows { namespace stanag { +using stanag_4607_segments = typename std::variant< stanag_4607_mission_segment, + stanag_4607_dwell_segment >; + // ---------------------------------------------------------------------------- /// Indicates the classification level of a packet enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_security_classification @@ -89,7 +99,6 @@ KWIVER_ALGO_STANAG_EXPORT std::ostream& operator<<( std::ostream& os, stanag_4607_packet_security const& value ); - // ---------------------------------------------------------------------------- DECLARE_STANAG_CMP( stanag_4607_packet_security ) @@ -150,22 +159,19 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet_header_format public: stanag_4607_packet_header_format(); - const size_t size = 32; // Number of bytes in packet header stanag_4607_packet_header read( ptr_t& ptr ) const; }; - // ---------------------------------------------------------------------------- /// Top level STANAG 4607 packet struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet { stanag_4607_packet_header header; std::vector< stanag_4607_segment_header > segment_headers; - std::vector< stanag_4607_mission_segment > segments; // TODO: make this any - // segment type + std::vector< stanag_4607_segments > segments; }; // ---------------------------------------------------------------------------- @@ -192,12 +198,11 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet_format read( ptr_t& ptr ) const; }; - // ---------------------------------------------------------------------------- /// Read the input data as a list of packets KWIVER_ALGO_STANAG_EXPORT std::vector< stanag_4607_packet > -read_stanag_4607_data( ptr_t& ptr ); +read_stanag_4607_data( std::vector< uint8_t > input_bytes ); } // Namespace stanag diff --git a/arrows/stanag/stanag_4607_segments.h b/arrows/stanag/stanag_4607_segments.h deleted file mode 100644 index 3b1ebbb2f1..0000000000 --- a/arrows/stanag/stanag_4607_segments.h +++ /dev/null @@ -1,324 +0,0 @@ -// This file is part of KWIVER, and is distributed under the -// OSI-approved BSD 3-Clause License. See top-level LICENSE file or -// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. - -/// \file -/// Defines a STANAG 4607 segment header and the various segment types - -#ifndef KWIVER_ARROWS_STANAG_4607_SEGMENTS_H_ -#define KWIVER_ARROWS_STANAG_4607_SEGMENTS_H_ - -#include "stanag_util.h" -#include - -#include -#include -#include -#include -#include -#include - -namespace kwiver { - -namespace arrows { - -namespace stanag { - -// ---------------------------------------------------------------------------- -/// The type of message contained in the segment -enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_type : uint16_t -{ - STANAG_4607_SEGMENT_TYPE_MISSION = 1, - STANAG_4607_SEGMENT_TYPE_DWELL = 2, - STANAG_4607_SEGMENT_TYPE_HRR = 3, - // Note: 4 is reserved - STANAG_4607_SEGMENT_TYPE_JOB_DEFINITION = 5, - STANAG_4607_SEGMENT_TYPE_FREE_TEXT = 6, - STANAG_4607_SEGMENT_TYPE_LOW_REFLECTIVITY_INDEX = 7, - STANAG_4607_SEGMENT_TYPE_GROUP = 8, - STANAG_4607_SEGMENT_TYPE_ATTACHED_TARGET = 9, - STANAG_4607_SEGMENT_TYPE_TEST_AND_STATUS = 10, - STANAG_4607_SEGMENT_TYPE_SYSTEM_SPECIFIC = 11, - STANAG_4607_SEGMENT_TYPE_PROCESSING_HISTORY = 12, - STANAG_4607_SEGMENT_TYPE_PLATFORM_LOCATION = 13, - // Note 14-100 are reserved for new segments - STANAG_4607_SEGMENT_TYPE_JOB_REQUEST = 101, - STANAG_4607_SEGMENT_TYPE_JOB_ACKNOWLEDGE = 102, - // Note: 103-127 are reserved for future use - // Note 128-255 are reserved for extensions - STANAG_4607_SEGMENT_TYPE_ENUM_END = 256, -}; - -// ---------------------------------------------------------------------------- -KWIVER_ALGO_STANAG_EXPORT -std::ostream& -operator<<( std::ostream& os, - stanag_4607_segment_type const& value ); - -// ---------------------------------------------------------------------------- -/// Identifies the type and size of the segment that follows -struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_header -{ - stanag_4607_segment_type segment_type; - size_t segment_size; -}; - -// ---------------------------------------------------------------------------- -KWIVER_ALGO_STANAG_EXPORT -std::ostream& -operator<<( std::ostream& os, stanag_4607_segment_header const& value ); - -// ---------------------------------------------------------------------------- -DECLARE_STANAG_CMP( stanag_4607_segment_header ) - -// ---------------------------------------------------------------------------- -class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_header_format - : public stanag_4607_segment_header -{ -public: - stanag_4607_segment_header_format(); - - - const size_t size = 5; // Number of bytes in the segment header - - stanag_4607_segment_header - read( ptr_t& ptr ) const; -}; - - -// ---------------------------------------------------------------------------- -/// Identifies the type of platform that originated the data -enum KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment_platform -{ - STANAG_4607_MISSION_PLATFORM_UNIDENTIFIED, - STANAG_4607_MISSION_PLATFORM_ACS, - STANAG_4607_MISSION_PLATFORM_ARL_M, - STANAG_4607_MISSION_PLATFORM_SENTINEL, - STANAG_4607_MISSION_PLATFORM_ROTARY_WING_RADAR, - STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_NAVY, - STANAG_4607_MISSION_PLATFORM_HORIZON, - STANAG_4607_MISSION_PLATFORM_E_8, - STANAG_4607_MISSION_PLATFORM_P_3C, - STANAG_4607_MISSION_PLATFORM_PREDATOR, - STANAG_4607_MISSION_PLATFORM_RADARSAT2, - STANAG_4607_MISSION_PLATFORM_U_2, - STANAG_4607_MISSION_PLATFORM_E_10, - STANAG_4607_MISSION_PLATFORM_UGS_SINGLE, - STANAG_4607_MISSION_PLATFORM_UGS_CLUSTER, - STANAG_4607_MISSION_PLATFORM_GROUND_BASED, - STANAG_4607_MISSION_PLATFORM_UAV_MARINES, - STANAG_4607_MISSION_PLATFORM_UAV_NAVY, - STANAG_4607_MISSION_PLATFORM_UAV_AIR_FORCE, - STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AIR_FORCE, - STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AUSTRALIA, - STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_GERMANY, - STANAG_4607_MISSION_PLATFORM_PAUL_REVERE, - STANAG_4607_MISSION_PLATFORM_MARINER_UAV, - STANAG_4607_MISSION_PLATFORM_BAC_11, - STANAG_4607_MISSION_PLATFORM_COYOTE, - STANAG_4607_MISSION_PLATFORM_KING_AIR, - STANAG_4607_MISSION_PLATFORM_LIMIT, - STANAG_4607_MISSION_PLATFORM_NRL_NP_3B, - STANAG_4607_MISSION_PLATFORM_SOSTAR_X, - STANAG_4607_MISSION_PLATFORM_WATCHKEEPER, - STANAG_4607_MISSION_PLATFORM_ALLIANCE_GROUND_SURVEILLANCE, - STANAG_4607_MISSION_PLATFORM_STRYKER, - STANAG_4607_MISSION_PLATFORM_AGS, - STANAG_4607_MISSION_PLATFORM_SIDM, - STANAG_4607_MISSION_PLATFORM_REAPER, - STANAG_4607_MISSION_PLATFORM_WARRIOR_A, - STANAG_4607_MISSION_PLATFORM_WARRIOR, - STANAG_4607_MISSION_PLATFORM_TWIN_OTTER, - // Note: 40-254 are available for future use - STANAG_4607_MISSION_PLATFORM_OTHER = 255, - STANAG_4607_MISSION_PLATFORM_ENUM_END, -}; - -// ---------------------------------------------------------------------------- -KWIVER_ALGO_STANAG_EXPORT -std::ostream& -operator<<( std::ostream& os, - stanag_4607_mission_segment_platform const& value ); - -// ---------------------------------------------------------------------------- -/// UTC time in which the mission originated -struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_reference_time -{ - int year; - int month; - int day; -}; - -// ---------------------------------------------------------------------------- -KWIVER_ALGO_STANAG_EXPORT -std::ostream& -operator<<( std::ostream& os, - stanag_4607_mission_reference_time const& value ); - - -// ---------------------------------------------------------------------------- -DECLARE_STANAG_CMP( stanag_4607_mission_reference_time ) - -// ---------------------------------------------------------------------------- -/// Information concerning the mission -struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment -{ - std::string mission_plan; - std::string flight_plan; - stanag_4607_mission_segment_platform platform_type; - std::string platform_configuration; - stanag_4607_mission_reference_time reference_time; -}; - -// ---------------------------------------------------------------------------- -KWIVER_ALGO_STANAG_EXPORT -std::ostream& -operator<<( std::ostream& os, stanag_4607_mission_segment const& value ); - -// ---------------------------------------------------------------------------- -DECLARE_STANAG_CMP( stanag_4607_mission_segment ) - -// ---------------------------------------------------------------------------- -/// Untyped base for STANAG formats -class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_data_format -{ -public: - explicit - stanag_4607_segment_data_format() {} - - virtual - ~stanag_4607_segment_data_format() = default; - - virtual stanag_4607_mission_segment // TODO: make this any segment type - read( ptr_t& ptr ) const = 0; -}; - -using stanag_4607_segment_data_format_sptr = - std::shared_ptr< stanag_4607_segment_data_format >; - -// ---------------------------------------------------------------------------- -/// Typed base for STANAG formats -template < class T > -class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_data_format_ - : public stanag_4607_segment_data_format -{ -public: - using data_type = T; - - explicit - stanag_4607_segment_data_format_() - {} - - virtual - ~stanag_4607_segment_data_format_() {} - - virtual T - read( ptr_t& ptr ) const = 0; -}; - -// ---------------------------------------------------------------------------- -/// The type, enumeration, and name of a segment -class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_type_traits -{ -public: - stanag_4607_segment_type_traits( uint16_t type, - std::string const& enum_name, - stanag_4607_segment_data_format_sptr format, - std::string const& name ) - : m_type{ type }, m_enum_name{ enum_name }, m_format{ format }, - m_name{ name } - {} - - /// Returns the enumeration value of the segment - uint16_t - type() const { return m_type; } - - /// Return a string version of the segment enumeration - std::string - enum_name() const { return m_enum_name; } - - /// Return the data format used to represent this segment's value. - stanag_4607_segment_data_format& - format() const { return *m_format; } - - /// Return the segment's name. - std::string - name() const { return m_name; } - -private: - uint16_t m_type; - std::string m_enum_name; - stanag_4607_segment_data_format_sptr m_format; - std::string m_name; -}; - -// ---------------------------------------------------------------------------- -/// Lookup table used to match a segment to its traits -class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_type_traits_lookup -{ -public: - using iterator = - typename std::vector< stanag_4607_segment_type_traits >::const_iterator; - using init_list = - typename std::initializer_list< stanag_4607_segment_type_traits >; - - stanag_4607_segment_type_traits_lookup( - std::initializer_list< stanag_4607_segment_type_traits > const& traits ); - - stanag_4607_segment_type_traits_lookup( - std::vector< stanag_4607_segment_type_traits > const& traits ); - - iterator - begin() const { return m_traits.begin(); } - - iterator - end() const { return m_traits.end(); } - - stanag_4607_segment_type_traits const& - by_type( uint16_t type ) const; - - /// Return the traits object with \p enum_name as its enum name. - stanag_4607_segment_type_traits const& - by_enum_name( std::string const& enum_name ) const; - -private: - void initialize(); - - - std::vector< stanag_4607_segment_type_traits > m_traits; - std::map< std::string, - stanag_4607_segment_type_traits const* > m_enum_name_to_traits; - std::map< uint16_t, - stanag_4607_segment_type_traits const* > m_type_to_traits; -}; - -// ---------------------------------------------------------------------------- -class KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment_format - : public stanag_4607_segment_data_format_< stanag_4607_mission_segment > -{ -public: - stanag_4607_mission_segment_format(); - - - const size_t size = 39; // Number of bytes in mission segment - - stanag_4607_mission_segment - read( ptr_t& ptr ) const override; -}; - -// ---------------------------------------------------------------------------- -/// -// TODO DWELL - -// ---------------------------------------------------------------------------- -/// Return a traits lookup object for segment types. -stanag_4607_segment_type_traits_lookup const& -stanag_4607_segment_type_traits_lookup_table(); - -} // namespace stanag - -} // namespace arrows - -} // namespace kwiver - -#endif diff --git a/arrows/stanag/stanag_util.cxx b/arrows/stanag/stanag_util.cxx index b7e6a7b507..f49cd2d46d 100644 --- a/arrows/stanag/stanag_util.cxx +++ b/arrows/stanag/stanag_util.cxx @@ -3,6 +3,7 @@ // https://github.com/Kitware/kwiver/blob/master/LICENSE for details. #include "stanag_util.h" +#include namespace klv = kwiver::arrows::klv; @@ -24,6 +25,7 @@ trim_whitespace( std::string input ) return input.substr( str_begin, ( str_end - str_begin ) + 1 ); } + } // namespace stanag } // namespace arrows diff --git a/arrows/stanag/stanag_util.h b/arrows/stanag/stanag_util.h index 4fc8808915..984e5069df 100644 --- a/arrows/stanag/stanag_util.h +++ b/arrows/stanag/stanag_util.h @@ -10,6 +10,7 @@ #include +#include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include From ada4b8d82237799650c7d21fc661bbe49f2bcc66 Mon Sep 17 00:00:00 2001 From: Hannah DeFazio Date: Tue, 24 Jan 2023 16:33:43 -0500 Subject: [PATCH 3/8] Add stanag 4607 to python --- .../segments/stanag_4607_dwell_segment.h | 54 +- .../segments/stanag_4607_mission_segment.h | 2 - arrows/stanag/segments/stanag_4607_segments.h | 3 +- arrows/stanag/stanag_4607_packet.cxx | 15 + arrows/stanag/stanag_4607_packet.h | 15 +- python/kwiver/arrows/CMakeLists.txt | 1 + python/kwiver/arrows/stanag/CMakeLists.txt | 30 + python/kwiver/arrows/stanag/__init__.py | 0 .../segments/stanag_4607_dwell_segment.cxx | 634 ++++++++++++++++++ .../segments/stanag_4607_dwell_segment.h | 19 + .../segments/stanag_4607_mission_segment.cxx | 158 +++++ .../segments/stanag_4607_mission_segment.h | 19 + .../stanag/segments/stanag_4607_segments.cxx | 79 +++ .../stanag/segments/stanag_4607_segments.h | 19 + .../arrows/stanag/stanag_4607_packet.cxx | 203 ++++++ .../kwiver/arrows/stanag/stanag_4607_packet.h | 19 + python/kwiver/arrows/stanag/stanag_module.cxx | 17 + 17 files changed, 1248 insertions(+), 39 deletions(-) create mode 100644 python/kwiver/arrows/stanag/CMakeLists.txt create mode 100644 python/kwiver/arrows/stanag/__init__.py create mode 100644 python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx create mode 100644 python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.h create mode 100644 python/kwiver/arrows/stanag/segments/stanag_4607_mission_segment.cxx create mode 100644 python/kwiver/arrows/stanag/segments/stanag_4607_mission_segment.h create mode 100644 python/kwiver/arrows/stanag/segments/stanag_4607_segments.cxx create mode 100644 python/kwiver/arrows/stanag/segments/stanag_4607_segments.h create mode 100644 python/kwiver/arrows/stanag/stanag_4607_packet.cxx create mode 100644 python/kwiver/arrows/stanag/stanag_4607_packet.h create mode 100644 python/kwiver/arrows/stanag/stanag_module.cxx diff --git a/arrows/stanag/segments/stanag_4607_dwell_segment.h b/arrows/stanag/segments/stanag_4607_dwell_segment.h index c1d8d72353..42b50830d7 100644 --- a/arrows/stanag/segments/stanag_4607_dwell_segment.h +++ b/arrows/stanag/segments/stanag_4607_dwell_segment.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace kwiver { @@ -46,7 +47,6 @@ KWIVER_ALGO_STANAG_EXPORT std::ostream& operator<<( std::ostream& os, stanag_4607_sensor_position const& value ); - // ---------------------------------------------------------------------------- DECLARE_STANAG_CMP( stanag_4607_sensor_position ) @@ -324,11 +324,11 @@ operator<<( std::ostream& os, /// The position of the reported detection. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_location { - kv::optional< double > hi_res_lat; - kv::optional< double > hi_res_long; - kv::optional< int > delta_lat; - kv::optional< int > delta_long; - kv::optional< int > geodetic_height; + std::optional< double > hi_res_lat; + std::optional< double > hi_res_long; + std::optional< int > delta_lat; + std::optional< int > delta_long; + std::optional< int > geodetic_height; }; // ---------------------------------------------------------------------------- @@ -355,16 +355,16 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_location_format /// Each target observed within the dwell. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_report { - kv::optional< int > mti_report_idx; - kv::optional< stanag_4607_target_location > location; - kv::optional< int > velocity_los; - kv::optional< int > wrap_velocity; - kv::optional< int > snr; - kv::optional< stanag_4607_target_classification > classification; - kv::optional< int > class_probability; - kv::optional< stanag_4607_target_measure_uncert > measurement_uncert; - kv::optional< stanag_4607_truth_tag > truth_tag; - kv::optional< int > radar_cross_sect; + std::optional< int > mti_report_idx; + std::optional< stanag_4607_target_location > location; + std::optional< int > velocity_los; + std::optional< int > wrap_velocity; + std::optional< int > snr; + std::optional< stanag_4607_target_classification > classification; + std::optional< int > class_probability; + std::optional< stanag_4607_target_measure_uncert > measurement_uncert; + std::optional< stanag_4607_truth_tag > truth_tag; + std::optional< int > radar_cross_sect; }; // ---------------------------------------------------------------------------- @@ -404,18 +404,18 @@ struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_segment int target_report_count; int dwell_time; stanag_4607_sensor_position sensor_position; - kv::optional< stanag_4607_scale_factor > scale_factor; - kv::optional< stanag_4607_sensor_pos_uncert > sensor_pos_uncert; - kv::optional< double > sensor_track; - kv::optional< int > sensor_speed; - kv::optional< int > sensor_vertical_vel; - kv::optional< int > sensor_track_uncert; - kv::optional< int > sensor_speed_uncert; - kv::optional< int > sensor_vertical_vel_uncert; - kv::optional< stanag_4607_orientation > platform_orient; + std::optional< stanag_4607_scale_factor > scale_factor; + std::optional< stanag_4607_sensor_pos_uncert > sensor_pos_uncert; + std::optional< double > sensor_track; + std::optional< int > sensor_speed; + std::optional< int > sensor_vertical_vel; + std::optional< int > sensor_track_uncert; + std::optional< int > sensor_speed_uncert; + std::optional< int > sensor_vertical_vel_uncert; + std::optional< stanag_4607_orientation > platform_orient; stanag_4607_dwell_area dwell_area; - kv::optional< stanag_4607_orientation > sensor_orientation; - kv::optional< int > min_detectable_vel; + std::optional< stanag_4607_orientation > sensor_orientation; + std::optional< int > min_detectable_vel; std::vector< stanag_4607_target_report > target_reports; }; diff --git a/arrows/stanag/segments/stanag_4607_mission_segment.h b/arrows/stanag/segments/stanag_4607_mission_segment.h index bd4bf6a9d7..70eab95ea0 100644 --- a/arrows/stanag/segments/stanag_4607_mission_segment.h +++ b/arrows/stanag/segments/stanag_4607_mission_segment.h @@ -125,8 +125,6 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_mission_segment_format public: stanag_4607_mission_segment_format(); - using data_type = stanag_4607_mission_segment; - stanag_4607_mission_segment read( ptr_t& ptr ) const; }; diff --git a/arrows/stanag/segments/stanag_4607_segments.h b/arrows/stanag/segments/stanag_4607_segments.h index d9dae20617..f8fe7ea919 100644 --- a/arrows/stanag/segments/stanag_4607_segments.h +++ b/arrows/stanag/segments/stanag_4607_segments.h @@ -69,12 +69,11 @@ DECLARE_STANAG_CMP( stanag_4607_segment_header ) // ---------------------------------------------------------------------------- class KWIVER_ALGO_STANAG_EXPORT stanag_4607_segment_header_format - : public stanag_4607_segment_header { public: stanag_4607_segment_header_format(); - const size_t size = 5; // Number of bytes in the segment header + static const size_t size = 5; // Number of bytes in the segment header stanag_4607_segment_header read( ptr_t& ptr ) const; diff --git a/arrows/stanag/stanag_4607_packet.cxx b/arrows/stanag/stanag_4607_packet.cxx index 2bdfd799c3..0110ccd319 100644 --- a/arrows/stanag/stanag_4607_packet.cxx +++ b/arrows/stanag/stanag_4607_packet.cxx @@ -5,6 +5,7 @@ #include "stanag_4607_packet.h" #include +#include #include namespace kwiver { @@ -320,6 +321,20 @@ read_stanag_4607_data( std::vector< uint8_t > input_bytes ) return result; } +// ---------------------------------------------------------------------------- +std::vector< stanag_4607_packet > +read_stanag_4607_file( std::string fn ) +{ + std::ifstream rf (fn, std::ios::binary); + if( !rf ) std::cerr << "DID NOT OPEN FILE " << fn << std::endl; + + std::vector input_bytes((std::istreambuf_iterator(rf)), + std::istreambuf_iterator()); + + auto result = read_stanag_4607_data( input_bytes ); + return result; +} + } // Namespace stanag diff --git a/arrows/stanag/stanag_4607_packet.h b/arrows/stanag/stanag_4607_packet.h index d2ac9ca60c..dbcc8d9b21 100644 --- a/arrows/stanag/stanag_4607_packet.h +++ b/arrows/stanag/stanag_4607_packet.h @@ -124,11 +124,6 @@ KWIVER_ALGO_STANAG_EXPORT std::ostream& operator<<( std::ostream& os, stanag_4607_exercise_indicator const& value ); -// ---------------------------------------------------------------------------- -KWIVER_ALGO_STANAG_EXPORT -std::ostream& -operator<<( std::ostream& os, stanag_4607_packet_security const& value ); - // ---------------------------------------------------------------------------- /// Provides basic information concerning the platform, the job, the mission, /// nationality, security, and the length of the packet. @@ -154,12 +149,11 @@ DECLARE_STANAG_CMP( stanag_4607_packet_header ) // ---------------------------------------------------------------------------- class KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet_header_format - : public stanag_4607_packet_header { public: stanag_4607_packet_header_format(); - const size_t size = 32; // Number of bytes in packet header + static const size_t size = 32; // Number of bytes in packet header stanag_4607_packet_header read( ptr_t& ptr ) const; @@ -189,7 +183,6 @@ DECLARE_STANAG_CMP( stanag_4607_packet ) // ---------------------------------------------------------------------------- class KWIVER_ALGO_STANAG_EXPORT stanag_4607_packet_format - : public stanag_4607_packet { public: stanag_4607_packet_format(); @@ -204,6 +197,12 @@ KWIVER_ALGO_STANAG_EXPORT std::vector< stanag_4607_packet > read_stanag_4607_data( std::vector< uint8_t > input_bytes ); +// ---------------------------------------------------------------------------- +/// Read the file as a list of packets +KWIVER_ALGO_STANAG_EXPORT +std::vector< stanag_4607_packet > +read_stanag_4607_file( std::string fn ); + } // Namespace stanag } // Namespace arrows diff --git a/python/kwiver/arrows/CMakeLists.txt b/python/kwiver/arrows/CMakeLists.txt index c10ddf4beb..9ff5067511 100644 --- a/python/kwiver/arrows/CMakeLists.txt +++ b/python/kwiver/arrows/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(serialize) add_subdirectory(core) +add_subdirectory(stanag) if(KWIVER_ENABLE_PYTHON_TESTS) add_subdirectory( tests ) diff --git a/python/kwiver/arrows/stanag/CMakeLists.txt b/python/kwiver/arrows/stanag/CMakeLists.txt new file mode 100644 index 0000000000..3ab35c9091 --- /dev/null +++ b/python/kwiver/arrows/stanag/CMakeLists.txt @@ -0,0 +1,30 @@ +set( stanag_python_headers + stanag_4607_packet.h + segments/stanag_4607_segments.h + segments/stanag_4607_mission_segment.h + segments/stanag_4607_dwell_segment.h + ) + + set( stanag_python_sources + stanag_4607_packet.cxx + stanag_module.cxx + segments/stanag_4607_segments.cxx + segments/stanag_4607_mission_segment.cxx + segments/stanag_4607_dwell_segment.cxx + ) + +kwiver_add_python_library( stanag + arrows/stanag + ${stanag_python_headers} + ${stanag_python_sources} +) + +target_link_libraries( python-arrows.stanag-stanag + PRIVATE ${PYTHON_LIBRARIES} pybind11::pybind11 + vital + kwiver_algo_stanag +) + +kwiver_add_python_module(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + arrows/stanag + __init__) diff --git a/python/kwiver/arrows/stanag/__init__.py b/python/kwiver/arrows/stanag/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx b/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx new file mode 100644 index 0000000000..e312599eec --- /dev/null +++ b/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx @@ -0,0 +1,634 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_4607_dwell_segment.h" + +using ptr_t = uint8_t const*; + +namespace kv = kwiver::vital; + +void +stanag_4607_dwell_segment( py::module& m ) +{ + py::class_< kas::stanag_4607_sensor_position >( m, + "stanag_4607_sensor_position" ) + .def( py::init( []( double latitude, double longitude, int altitude){ + return kas::stanag_4607_sensor_position{ latitude, + longitude, + altitude }; + } ) ) + .def_readwrite( "latitude", &kas::stanag_4607_sensor_position::latitude ) + .def_readwrite( "longitude", &kas::stanag_4607_sensor_position::longitude ) + .def_readwrite( "altitude", &kas::stanag_4607_sensor_position::altitude ) + .def( "__str__", + []( kas::stanag_4607_sensor_position const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_scale_factor >( m, "stanag_4607_scale_factor" ) + .def( py::init( []( int lat_scale, int long_scale ){ + return kas::stanag_4607_scale_factor{ lat_scale, + long_scale }; + } ) ) + .def_readwrite( "lat_scale", &kas::stanag_4607_scale_factor::lat_scale ) + .def_readwrite( "long_scale", &kas::stanag_4607_scale_factor::long_scale ) + .def( "__str__", + []( kas::stanag_4607_scale_factor const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_scale_factor_format >( m, + "stanag_4607_scale_factor_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_scale_factor_format{}.read( ptr ); + } ); + + py::class_< kas::stanag_4607_sensor_pos_uncert >( m, + "stanag_4607_sensor_pos_uncert" ) + .def( py::init( []( int along_track, int cross_track, int altitude ){ + return kas::stanag_4607_sensor_pos_uncert{ along_track, + cross_track, + altitude }; + } ) ) + .def_readwrite( "along_track", + &kas::stanag_4607_sensor_pos_uncert::along_track ) + .def_readwrite( "cross_track", + &kas::stanag_4607_sensor_pos_uncert::cross_track ) + .def_readwrite( "altitude", &kas::stanag_4607_sensor_pos_uncert::altitude ) + .def( "__str__", + []( kas::stanag_4607_sensor_pos_uncert const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_sensor_pos_uncert_format >( m, + "stanag_4607_sensor_pos_uncert_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_sensor_pos_uncert_format{}.read( ptr ); + } ); + + py::class_< kas::stanag_4607_orientation >( m, "stanag_4607_orientation" ) + .def( py::init( []( double heading, double pitch, double roll ){ + return kas::stanag_4607_orientation{ heading, pitch, + roll }; + } ) ) + .def_readwrite( "heading", &kas::stanag_4607_orientation::heading ) + .def_readwrite( "pitch", &kas::stanag_4607_orientation::pitch ) + .def_readwrite( "roll", &kas::stanag_4607_orientation::roll ) + .def( "__str__", + []( kas::stanag_4607_orientation const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_orientation_format >( m, + "stanag_4607_orientation_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_orientation_format{}.read( ptr ); + } ); + + py::class_< kas::stanag_4607_dwell_area >( m, "stanag_4607_dwell_area" ) + .def( py::init( []( double center_lat, double center_long, + double range_half_ext, double dwell_angle_half_ext ){ + return kas::stanag_4607_dwell_area{ center_lat, + center_long, + range_half_ext, + dwell_angle_half_ext }; + } ) ) + .def_readwrite( "center_lat", &kas::stanag_4607_dwell_area::center_lat ) + .def_readwrite( "center_long", &kas::stanag_4607_dwell_area::center_long ) + .def_readwrite( "range_half_ext", + &kas::stanag_4607_dwell_area::range_half_ext ) + .def_readwrite( "dwell_angle_half_ext", + &kas::stanag_4607_dwell_area::dwell_angle_half_ext ) + .def( "__str__", + []( kas::stanag_4607_dwell_area const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::enum_< kas::stanag_4607_target_classification >( m, + "stanag_4607_target_classification" ) + .value( "STANAG_4607_TARGET_CLASS_NO_INFO_LIVE", + kas::STANAG_4607_TARGET_CLASS_NO_INFO_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_TRACKED_VEHICLE_LIVE", + kas::STANAG_4607_TARGET_CLASS_TRACKED_VEHICLE_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_WHEELED_VEHICLE_LIVE", + kas::STANAG_4607_TARGET_CLASS_WHEELED_VEHICLE_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_ROTARY_WING_AIRCRAFT_LIVE", + kas::STANAG_4607_TARGET_CLASS_ROTARY_WING_AIRCRAFT_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_FIXED_WING_AIRCRAFT_LIVE", + kas::STANAG_4607_TARGET_CLASS_FIXED_WING_AIRCRAFT_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_STATIONARY_ROTATOR_LIVE", + kas::STANAG_4607_TARGET_CLASS_STATIONARY_ROTATOR_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_MARITIME_LIVE", + kas::STANAG_4607_TARGET_CLASS_MARITIME_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_BEACON_LIVE", + kas::STANAG_4607_TARGET_CLASS_BEACON_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_AMPHIBIOUS_LIVE", + kas::STANAG_4607_TARGET_CLASS_AMPHIBIOUS_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_PERSON_LIVE", + kas::STANAG_4607_TARGET_CLASS_PERSON_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_VEHICLE_LIVE", + kas::STANAG_4607_TARGET_CLASS_VEHICLE_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_ANIMAL_LIVE", + kas::STANAG_4607_TARGET_CLASS_ANIMAL_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_LIVE_LAND", + kas::STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_LIVE_LAND ) + .value( "STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_LIVE_MARITIME", + kas::STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_LIVE_MARITIME ) + .value( "STANAG_4607_TARGET_CLASS_OTHER_LIVE", + kas::STANAG_4607_TARGET_CLASS_OTHER_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_UNKNOWN_LIVE", + kas::STANAG_4607_TARGET_CLASS_UNKNOWN_LIVE ) + .value( "STANAG_4607_TARGET_CLASS_NO_INFO_SIM", + kas::STANAG_4607_TARGET_CLASS_NO_INFO_SIM ) + .value( "STANAG_4607_TARGET_CLASS_TRACKED_VEHICLE_SIM", + kas::STANAG_4607_TARGET_CLASS_TRACKED_VEHICLE_SIM ) + .value( "STANAG_4607_TARGET_CLASS_WHEELED_VEHICLE_SIM", + kas::STANAG_4607_TARGET_CLASS_WHEELED_VEHICLE_SIM ) + .value( "STANAG_4607_TARGET_CLASS_ROTARY_WING_AIRCRAFT_SIM", + kas::STANAG_4607_TARGET_CLASS_ROTARY_WING_AIRCRAFT_SIM ) + .value( "STANAG_4607_TARGET_CLASS_FIXED_WING_AIRCRAFT_SIM", + kas::STANAG_4607_TARGET_CLASS_FIXED_WING_AIRCRAFT_SIM ) + .value( "STANAG_4607_TARGET_CLASS_STATIONARY_ROTATOR_SIM", + kas::STANAG_4607_TARGET_CLASS_STATIONARY_ROTATOR_SIM ) + .value( "STANAG_4607_TARGET_CLASS_MARITIME_SIM", + kas::STANAG_4607_TARGET_CLASS_MARITIME_SIM ) + .value( "STANAG_4607_TARGET_CLASS_BEACON_SIM", + kas::STANAG_4607_TARGET_CLASS_BEACON_SIM ) + .value( "STANAG_4607_TARGET_CLASS_AMPHIBIOUS_SIM", + kas::STANAG_4607_TARGET_CLASS_AMPHIBIOUS_SIM ) + .value( "STANAG_4607_TARGET_CLASS_PERSON_SIM", + kas::STANAG_4607_TARGET_CLASS_PERSON_SIM ) + .value( "STANAG_4607_TARGET_CLASS_VEHICLE_SIM", + kas::STANAG_4607_TARGET_CLASS_VEHICLE_SIM ) + .value( "STANAG_4607_TARGET_CLASS_ANIMAL_SIM", + kas::STANAG_4607_TARGET_CLASS_ANIMAL_SIM ) + .value( "STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_SIM_LAND", + kas::STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_SIM_LAND ) + .value( "STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_SIM_MARITIME", + kas::STANAG_4607_TARGET_CLASS_LARGE_MULTI_RETURN_SIM_MARITIME ) + .value( "STANAG_4607_TARGET_CLASS_TAGGING_DEVICE", + kas::STANAG_4607_TARGET_CLASS_TAGGING_DEVICE ) + .value( "STANAG_4607_TARGET_CLASS_OTHER_SIM", + kas::STANAG_4607_TARGET_CLASS_OTHER_SIM ) + .value( "STANAG_4607_TARGET_CLASS_UNKNOWN_SIM", + kas::STANAG_4607_TARGET_CLASS_UNKNOWN_SIM ) + .value( "STANAG_4607_TARGET_CLASS_ENUM_END", + kas::STANAG_4607_TARGET_CLASS_ENUM_END ) + .def( "__str__", + []( kas::stanag_4607_target_classification const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_target_measure_uncert >( m, + "stanag_4607_target_measure_uncert" ) + .def( py::init( []( int slant_range, int cross_range, int height, + int radial_velocity ){ + return kas::stanag_4607_target_measure_uncert{ + slant_range, cross_range, height, radial_velocity }; + } ) ) + .def_readwrite( "slant_range", + &kas::stanag_4607_target_measure_uncert::slant_range ) + .def_readwrite( "cross_range", + &kas::stanag_4607_target_measure_uncert::cross_range ) + .def_readwrite( "height", &kas::stanag_4607_target_measure_uncert::height ) + .def_readwrite( "radial_velocity", + &kas::stanag_4607_target_measure_uncert::radial_velocity ) + .def( "__str__", + []( kas::stanag_4607_target_measure_uncert const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_target_measure_uncert_format >( m, + "stanag_4607_target_measure_uncert_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_target_measure_uncert_format{}.read( ptr ); + } ); + + py::class_< kas::stanag_4607_truth_tag >( m, "stanag_4607_truth_tag" ) + .def( py::init( []( int application, int entity ){ + return kas::stanag_4607_truth_tag{ application, entity }; + } ) ) + .def_readwrite( "application", &kas::stanag_4607_truth_tag::application ) + .def_readwrite( "entity", &kas::stanag_4607_truth_tag::entity ) + .def( "__str__", + []( kas::stanag_4607_truth_tag const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_truth_tag_format >( m, + "stanag_4607_truth_tag_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_truth_tag_format{}.read( ptr ); + } ); + + py::enum_< kas::stanag_4607_dwell_existence_mask_bit >( m, + "stanag_4607_dwell_existence_mask_bit" ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_RADAR_CROSS_SECT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_RADAR_CROSS_SECT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_TRUTH_TAG_ENTITY", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_TRUTH_TAG_ENTITY ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_TRUTH_TAG_APPL", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_TRUTH_TAG_APPL ) + .value( + "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_RADIAL_VEL", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_RADIAL_VEL ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_HEIGHT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_HEIGHT ) + .value( + "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_CROSS_RNAGE", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_CROSS_RNAGE ) + .value( + "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_SLANT_RANGE", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_MEASURE_SLANT_RANGE ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_CLASS_PROB", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_CLASS_PROB ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_CLASS", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_CLASS ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_SNR", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_SNR ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_WRAP_VEL", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_WRAP_VEL ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_VEL_LOS", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_VEL_LOS ) + .value( + "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_GEODETIC_HEIGHT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_GEODETIC_HEIGHT ) + .value( + "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_DELTA_LONG", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_DELTA_LONG ) + .value( + "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_DELTA_LAT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_DELTA_LAT ) + .value( + "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_HI_RES_LONG", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_HI_RES_LONG ) + .value( + "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_HI_RES_LAT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_HI_RES_LAT ) + .value( + "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_MTI_REPORT_IDX", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_MTI_REPORT_IDX ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_MIN_DETECT_VEL", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_MIN_DETECT_VEL ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_ORIENT_ROLL", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_ORIENT_ROLL ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_OREINT_PITCH", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_OREINT_PITCH ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_OREINT_HEADING", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_OREINT_HEADING ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_DWELL_ANGLE_HALF", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_DWELL_ANGLE_HALF ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_RANGE_HALF", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_RANGE_HALF ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_CENTER_LONG", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_CENTER_LONG ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_CENTER_LAT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_AREA_CENTER_LAT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_OREINT_ROLL", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_OREINT_ROLL ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_ORIENT_PITCH", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_ORIENT_PITCH ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_OREINT_HEADING", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_PLATFORM_OREINT_HEADING ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_VERTICAL_VEL_UNCERT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_VERTICAL_VEL_UNCERT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_SPEED_UNCERT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_SPEED_UNCERT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK_UNCERT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK_UNCERT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_VERTICAL_VEL", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_VERTICAL_VEL ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_SPEED", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_SPEED ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_ALT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_ALT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_CROSS_TRACK", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_CROSS_TRACK ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_ALONG_TRACK", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_POS_ALONG_TRACK ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SCALE_FACT_LONG", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SCALE_FACT_LONG ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SCALE_FACT_LAT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SCALE_FACT_LAT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_ALT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_ALT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_LONG", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_LONG ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_LAT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_LAT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_TIME", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_TIME ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_COUNT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_COUNT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_LAST_DWELL_REVISIT", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_LAST_DWELL_REVISIT ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_INDEX", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_DWELL_INDEX ) + .value( "STANAG_4607_DWELL_EXIST_MASK_BIT_REVISIT_INDEX", + kas::STANAG_4607_DWELL_EXIST_MASK_BIT_REVISIT_INDEX ) + .def( "__str__", + []( kas::stanag_4607_dwell_existence_mask_bit const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_target_location >( m, + "stanag_4607_target_location" ) + .def( py::init( []( double hi_res_lat, double hi_res_long, int delta_lat, + int delta_long, int geodetic_height ){ + return kas::stanag_4607_target_location{ hi_res_lat, + hi_res_long, + delta_lat, + delta_long, + geodetic_height }; + } ) ) + .def_readwrite( "hi_res_lat", + &kas::stanag_4607_target_location::hi_res_lat ) + .def_readwrite( "hi_res_long", + &kas::stanag_4607_target_location::hi_res_long ) + .def_readwrite( "delta_lat", &kas::stanag_4607_target_location::delta_lat ) + .def_readwrite( "delta_long", + &kas::stanag_4607_target_location::delta_long ) + .def_readwrite( "geodetic_height", + &kas::stanag_4607_target_location::geodetic_height ) + .def( "__str__", + []( kas::stanag_4607_target_location const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_target_location_format >( m, + "stanag_4607_target_location_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr, + std::set< kas::stanag_4607_dwell_existence_mask_bit > + existence_mask ){ + return kas::stanag_4607_target_location_format{}.read( ptr, + existence_mask ); + } ); + + py::class_< kas::stanag_4607_target_report >( m, + "stanag_4607_target_report" ) + .def( py::init( [](std::optional< int > mti_report_idx, + std::optional< kas::stanag_4607_target_location > + location, + std::optional< int > velocity_los, + std::optional< int > wrap_velocity, + std::optional< int > snr, + std::optional< kas::stanag_4607_target_classification > + classification, + std::optional< int > class_probability, + std::optional< kas::stanag_4607_target_measure_uncert > + measurement_uncert, + std::optional< kas::stanag_4607_truth_tag > truth_tag, + std::optional< int > radar_cross_sect ){ + auto result = kas::stanag_4607_target_report{}; + + if( mti_report_idx.has_value() ) + { + result.mti_report_idx = *mti_report_idx; + } + if( location.has_value() ) + { + result.location = *location; + } + if( velocity_los.has_value() ) + { + result.velocity_los = *velocity_los; + } + if( wrap_velocity.has_value() ) + { + result.wrap_velocity = *wrap_velocity; + } + if( snr.has_value() ) { result.snr = *snr; } + if( classification.has_value() ) + { + result.classification = *classification; + } + if( class_probability.has_value() ) + { + result.class_probability = *class_probability; + } + if( measurement_uncert.has_value() ) + { + result.measurement_uncert = *measurement_uncert; + } + if( truth_tag.has_value() ) + { + result.truth_tag = *truth_tag; + } + if( radar_cross_sect.has_value() ) + { + result.radar_cross_sect = *radar_cross_sect; + } + + return result; + } ) ) + .def_readwrite( "mti_report_idx", + &kas::stanag_4607_target_report::mti_report_idx ) + .def_readwrite( "location", &kas::stanag_4607_target_report::location ) + .def_readwrite( "velocity_los", + &kas::stanag_4607_target_report::velocity_los ) + .def_readwrite( "wrap_velocity", + &kas::stanag_4607_target_report::wrap_velocity ) + .def_readwrite( "snr", &kas::stanag_4607_target_report::snr ) + .def_readwrite( "classification", + &kas::stanag_4607_target_report::classification ) + .def_readwrite( "class_probability", + &kas::stanag_4607_target_report::class_probability ) + .def_readwrite( "measurement_uncert", + &kas::stanag_4607_target_report::measurement_uncert ) + .def_readwrite( "truth_tag", &kas::stanag_4607_target_report::truth_tag ) + .def_readwrite( "radar_cross_sect", + &kas::stanag_4607_target_report::radar_cross_sect ) + .def( "__str__", + []( kas::stanag_4607_target_report const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_target_report_format >( m, + "stanag_4607_target_report_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr, + std::set< kas::stanag_4607_dwell_existence_mask_bit > + existence_mask ){ + return kas::stanag_4607_target_report_format{}.read( ptr, + existence_mask ); + } ); + + py::class_< kas::stanag_4607_dwell_segment >( m, + "stanag_4607_dwell_segment" ) + .def( py::init( []( std::set< kas::stanag_4607_dwell_existence_mask_bit > + existence_mask, + int revisit_index, int dwell_index, + int last_dwell_of_revisit, + int target_report_count, int dwell_time, + kas::stanag_4607_sensor_position sensor_position, + std::optional< kas::stanag_4607_scale_factor > + scale_factor, + std::optional< kas::stanag_4607_sensor_pos_uncert > + sensor_pos_uncert, + std::optional< double > sensor_track, + std::optional< int > sensor_speed, + std::optional< int > sensor_vertical_vel, + std::optional< int > sensor_track_uncert, + std::optional< int > sensor_speed_uncert, + std::optional< int > sensor_vertical_vel_uncert, + std::optional< kas::stanag_4607_orientation > + platform_orient, + kas::stanag_4607_dwell_area dwell_area, + std::optional< kas::stanag_4607_orientation > + sensor_orientation, + std::optional< int > min_detectable_vel, + std::vector< kas::stanag_4607_target_report > + target_reports ){ + auto result = kas::stanag_4607_dwell_segment{}; + + // Mandatory fields + result.existence_mask = existence_mask; + result.revisit_index = revisit_index; + result.dwell_index = dwell_index; + result.last_dwell_of_revisit = last_dwell_of_revisit; + result.target_report_count = target_report_count; + result.dwell_time = dwell_time; + result.sensor_position = sensor_position; + result.dwell_area = dwell_area; + result.target_reports = target_reports; + + // Optional/Conditional fields + if( scale_factor.has_value() ) + { + result.scale_factor = *scale_factor; + } + if( sensor_pos_uncert.has_value() ) + { + result.sensor_pos_uncert = *sensor_pos_uncert; + } + if( sensor_track.has_value() ) + { + result.sensor_track = *sensor_track; + } + if( sensor_speed.has_value() ) + { + result.sensor_speed = *sensor_speed; + } + if( sensor_vertical_vel.has_value() ) + { + result.sensor_vertical_vel = *sensor_vertical_vel; + } + if( sensor_track_uncert.has_value() ) + { + result.sensor_track_uncert = *sensor_track_uncert; + } + if( sensor_speed_uncert.has_value() ) + { + result.sensor_speed_uncert = *sensor_speed_uncert; + } + if( sensor_vertical_vel_uncert.has_value() ) + { + result.sensor_vertical_vel_uncert = + *sensor_vertical_vel_uncert; + } + if( platform_orient.has_value() ) + { + result.platform_orient = *platform_orient; + } + if( sensor_orientation.has_value() ) + { + result.sensor_orientation = *sensor_orientation; + } + if( min_detectable_vel.has_value() ) + { + result.min_detectable_vel = *min_detectable_vel; + } + + return result; + } ) ) + .def_readwrite( "existence_mask", + &kas::stanag_4607_dwell_segment::existence_mask ) + .def_readwrite( "revisit_index", + &kas::stanag_4607_dwell_segment::revisit_index ) + .def_readwrite( "dwell_index", + &kas::stanag_4607_dwell_segment::dwell_index ) + .def_readwrite( "last_dwell_of_revisit", + &kas::stanag_4607_dwell_segment::last_dwell_of_revisit ) + .def_readwrite( "target_report_count", + &kas::stanag_4607_dwell_segment::target_report_count ) + .def_readwrite( "dwell_time", &kas::stanag_4607_dwell_segment::dwell_time ) + .def_readwrite( "sensor_position", + &kas::stanag_4607_dwell_segment::sensor_position ) + .def_readwrite( "scale_factor", + &kas::stanag_4607_dwell_segment::scale_factor ) + .def_readwrite( "sensor_pos_uncert", + &kas::stanag_4607_dwell_segment::sensor_pos_uncert ) + .def_readwrite( "sensor_track", + &kas::stanag_4607_dwell_segment::sensor_track ) + .def_readwrite( "sensor_speed", + &kas::stanag_4607_dwell_segment::sensor_speed ) + .def_readwrite( "sensor_vertical_vel", + &kas::stanag_4607_dwell_segment::sensor_vertical_vel ) + .def_readwrite( "sensor_track_uncert", + &kas::stanag_4607_dwell_segment::sensor_track_uncert ) + .def_readwrite( "sensor_speed_uncert", + &kas::stanag_4607_dwell_segment::sensor_speed_uncert ) + .def_readwrite( "sensor_vertical_vel_uncert", + &kas::stanag_4607_dwell_segment::sensor_vertical_vel_uncert ) + .def_readwrite( "platform_orient", + &kas::stanag_4607_dwell_segment::platform_orient ) + .def_readwrite( "dwell_area", &kas::stanag_4607_dwell_segment::dwell_area ) + .def_readwrite( "sensor_orientation", + &kas::stanag_4607_dwell_segment::sensor_orientation ) + .def_readwrite( "min_detectable_vel", + &kas::stanag_4607_dwell_segment::min_detectable_vel ) + .def_readwrite( "target_reports", + &kas::stanag_4607_dwell_segment::target_reports ) + .def( "__str__", + []( kas::stanag_4607_dwell_segment const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_dwell_segment_format >( m, + "stanag_4607_dwell_segment_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_dwell_segment_format{}.read( ptr ); + } ); +} diff --git a/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.h b/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.h new file mode 100644 index 0000000000..fd08915c87 --- /dev/null +++ b/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.h @@ -0,0 +1,19 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#ifndef KWIVER_PYTHON_ARROW_STANAG_4607_DWELL_SEGMENT_H_ +#define KWIVER_PYTHON_ARROW_STANAG_4607_DWELL_SEGMENT_H_ + +#include +#include + +#include + +namespace py = pybind11; + +namespace kas = kwiver::arrows::stanag; + +void stanag_4607_dwell_segment( py::module& m ); + +#endif diff --git a/python/kwiver/arrows/stanag/segments/stanag_4607_mission_segment.cxx b/python/kwiver/arrows/stanag/segments/stanag_4607_mission_segment.cxx new file mode 100644 index 0000000000..a9d4e7af78 --- /dev/null +++ b/python/kwiver/arrows/stanag/segments/stanag_4607_mission_segment.cxx @@ -0,0 +1,158 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_4607_mission_segment.h" + +using ptr_t = uint8_t const*; + +void +stanag_4607_mission_segment( py::module& m ) +{ + py::enum_< kas::stanag_4607_mission_segment_platform >( m, + "stanag_4607_mission_segment_platform" ) + .value( "STANAG_4607_MISSION_PLATFORM_UNIDENTIFIED", + kas::STANAG_4607_MISSION_PLATFORM_UNIDENTIFIED ) + .value( "STANAG_4607_MISSION_PLATFORM_ACS", + kas::STANAG_4607_MISSION_PLATFORM_ACS ) + .value( "STANAG_4607_MISSION_PLATFORM_ARL_M", + kas::STANAG_4607_MISSION_PLATFORM_ARL_M ) + .value( "STANAG_4607_MISSION_PLATFORM_SENTINEL", + kas::STANAG_4607_MISSION_PLATFORM_SENTINEL ) + .value( "STANAG_4607_MISSION_PLATFORM_ROTARY_WING_RADAR", + kas::STANAG_4607_MISSION_PLATFORM_ROTARY_WING_RADAR ) + .value( "STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_NAVY", + kas::STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_NAVY ) + .value( "STANAG_4607_MISSION_PLATFORM_HORIZON", + kas::STANAG_4607_MISSION_PLATFORM_HORIZON ) + .value( "STANAG_4607_MISSION_PLATFORM_E_8", + kas::STANAG_4607_MISSION_PLATFORM_E_8 ) + .value( "STANAG_4607_MISSION_PLATFORM_P_3C", + kas::STANAG_4607_MISSION_PLATFORM_P_3C ) + .value( "STANAG_4607_MISSION_PLATFORM_PREDATOR", + kas::STANAG_4607_MISSION_PLATFORM_PREDATOR ) + .value( "STANAG_4607_MISSION_PLATFORM_RADARSAT2", + kas::STANAG_4607_MISSION_PLATFORM_RADARSAT2 ) + .value( "STANAG_4607_MISSION_PLATFORM_U_2", + kas::STANAG_4607_MISSION_PLATFORM_U_2 ) + .value( "STANAG_4607_MISSION_PLATFORM_E_10", + kas::STANAG_4607_MISSION_PLATFORM_E_10 ) + .value( "STANAG_4607_MISSION_PLATFORM_UGS_SINGLE", + kas::STANAG_4607_MISSION_PLATFORM_UGS_SINGLE ) + .value( "STANAG_4607_MISSION_PLATFORM_UGS_CLUSTER", + kas::STANAG_4607_MISSION_PLATFORM_UGS_CLUSTER ) + .value( "STANAG_4607_MISSION_PLATFORM_GROUND_BASED", + kas::STANAG_4607_MISSION_PLATFORM_GROUND_BASED ) + .value( "STANAG_4607_MISSION_PLATFORM_UAV_MARINES", + kas::STANAG_4607_MISSION_PLATFORM_UAV_MARINES ) + .value( "STANAG_4607_MISSION_PLATFORM_UAV_NAVY", + kas::STANAG_4607_MISSION_PLATFORM_UAV_NAVY ) + .value( "STANAG_4607_MISSION_PLATFORM_UAV_AIR_FORCE", + kas::STANAG_4607_MISSION_PLATFORM_UAV_AIR_FORCE ) + .value( "STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AIR_FORCE", + kas::STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AIR_FORCE ) + .value( "STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AUSTRALIA", + kas::STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_AUSTRALIA ) + .value( "STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_GERMANY", + kas::STANAG_4607_MISSION_PLATFORM_GLOBAL_HAWK_GERMANY ) + .value( "STANAG_4607_MISSION_PLATFORM_PAUL_REVERE", + kas::STANAG_4607_MISSION_PLATFORM_PAUL_REVERE ) + .value( "STANAG_4607_MISSION_PLATFORM_MARINER_UAV", + kas::STANAG_4607_MISSION_PLATFORM_MARINER_UAV ) + .value( "STANAG_4607_MISSION_PLATFORM_BAC_11", + kas::STANAG_4607_MISSION_PLATFORM_BAC_11 ) + .value( "STANAG_4607_MISSION_PLATFORM_COYOTE", + kas::STANAG_4607_MISSION_PLATFORM_COYOTE ) + .value( "STANAG_4607_MISSION_PLATFORM_KING_AIR", + kas::STANAG_4607_MISSION_PLATFORM_KING_AIR ) + .value( "STANAG_4607_MISSION_PLATFORM_LIMIT", + kas::STANAG_4607_MISSION_PLATFORM_LIMIT ) + .value( "STANAG_4607_MISSION_PLATFORM_NRL_NP_3B", + kas::STANAG_4607_MISSION_PLATFORM_NRL_NP_3B ) + .value( "STANAG_4607_MISSION_PLATFORM_SOSTAR_X", + kas::STANAG_4607_MISSION_PLATFORM_SOSTAR_X ) + .value( "STANAG_4607_MISSION_PLATFORM_WATCHKEEPER", + kas::STANAG_4607_MISSION_PLATFORM_WATCHKEEPER ) + .value( "STANAG_4607_MISSION_PLATFORM_ALLIANCE_GROUND_SURVEILLANCE", + kas::STANAG_4607_MISSION_PLATFORM_ALLIANCE_GROUND_SURVEILLANCE ) + .value( "STANAG_4607_MISSION_PLATFORM_STRYKER", + kas::STANAG_4607_MISSION_PLATFORM_STRYKER ) + .value( "STANAG_4607_MISSION_PLATFORM_AGS", + kas::STANAG_4607_MISSION_PLATFORM_AGS ) + .value( "STANAG_4607_MISSION_PLATFORM_SIDM", + kas::STANAG_4607_MISSION_PLATFORM_SIDM ) + .value( "STANAG_4607_MISSION_PLATFORM_REAPER", + kas::STANAG_4607_MISSION_PLATFORM_REAPER ) + .value( "STANAG_4607_MISSION_PLATFORM_WARRIOR_A", + kas::STANAG_4607_MISSION_PLATFORM_WARRIOR_A ) + .value( "STANAG_4607_MISSION_PLATFORM_WARRIOR", + kas::STANAG_4607_MISSION_PLATFORM_WARRIOR ) + .value( "STANAG_4607_MISSION_PLATFORM_TWIN_OTTER", + kas::STANAG_4607_MISSION_PLATFORM_TWIN_OTTER ) + .value( "STANAG_4607_MISSION_PLATFORM_OTHER", + kas::STANAG_4607_MISSION_PLATFORM_OTHER ) + .value( "STANAG_4607_MISSION_PLATFORM_ENUM_END", + kas::STANAG_4607_MISSION_PLATFORM_ENUM_END ) + .def( "__str__", + []( kas::stanag_4607_mission_segment_platform const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_mission_reference_time >( m, + "stanag_4607_mission_reference_time" ) + .def( py::init( + []( int year, int month, int day ){ + return kas::stanag_4607_mission_reference_time{ year, month, + day }; + } ) + ) + .def_readwrite( "year", &kas::stanag_4607_mission_reference_time::year ) + .def_readwrite( "month", &kas::stanag_4607_mission_reference_time::month ) + .def_readwrite( "day", &kas::stanag_4607_mission_reference_time::day ) + .def( "__str__", + []( kas::stanag_4607_mission_reference_time const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_mission_segment >( m, + "stanag_4607_mission_segment" ) + .def( py::init( + []( std::string mission_plan, std::string flight_plan, + kas::stanag_4607_mission_segment_platform platform_type, + std::string platform_configuration, + kas::stanag_4607_mission_reference_time reference_time ){ + return kas::stanag_4607_mission_segment{ mission_plan, + flight_plan, + platform_type, + platform_configuration, + reference_time }; + } ) ) + .def_readwrite( "mission_plan", + &kas::stanag_4607_mission_segment::mission_plan ) + .def_readwrite( "flight_plan", + &kas::stanag_4607_mission_segment::flight_plan ) + .def_readwrite( "platform_type", + &kas::stanag_4607_mission_segment::platform_type ) + .def_readwrite( "platform_configuration", + &kas::stanag_4607_mission_segment::platform_configuration ) + .def_readwrite( "reference_time", + &kas::stanag_4607_mission_segment::reference_time ) + .def( "__str__", + []( kas::stanag_4607_mission_segment const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_mission_segment_format >( m, + "stanag_4607_mission_segment_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_mission_segment_format{}.read( ptr ); + } ); +} diff --git a/python/kwiver/arrows/stanag/segments/stanag_4607_mission_segment.h b/python/kwiver/arrows/stanag/segments/stanag_4607_mission_segment.h new file mode 100644 index 0000000000..38c9a907e1 --- /dev/null +++ b/python/kwiver/arrows/stanag/segments/stanag_4607_mission_segment.h @@ -0,0 +1,19 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#ifndef KWIVER_PYTHON_ARROW_STANAG_4607_MISSION_SEGMENT_H_ +#define KWIVER_PYTHON_ARROW_STANAG_4607_MISSION_SEGMENT_H_ + +#include +#include + +#include + +namespace py = pybind11; + +namespace kas = kwiver::arrows::stanag; + +void stanag_4607_mission_segment( py::module& m ); + +#endif diff --git a/python/kwiver/arrows/stanag/segments/stanag_4607_segments.cxx b/python/kwiver/arrows/stanag/segments/stanag_4607_segments.cxx new file mode 100644 index 0000000000..f014f29a11 --- /dev/null +++ b/python/kwiver/arrows/stanag/segments/stanag_4607_segments.cxx @@ -0,0 +1,79 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_4607_segments.h" + +using ptr_t = uint8_t const*; + +void +stanag_4607_segments( py::module& m ) +{ + py::enum_< kas::stanag_4607_segment_type >( m, "stanag_4607_segment_type" ) + .value( "STANAG_4607_SEGMENT_TYPE_MISSION", + kas::STANAG_4607_SEGMENT_TYPE_MISSION ) + .value( "STANAG_4607_SEGMENT_TYPE_DWELL", + kas::STANAG_4607_SEGMENT_TYPE_DWELL ) + .value( "STANAG_4607_SEGMENT_TYPE_HRR", kas::STANAG_4607_SEGMENT_TYPE_HRR ) + .value( "STANAG_4607_SEGMENT_TYPE_JOB_DEFINITION", + kas::STANAG_4607_SEGMENT_TYPE_JOB_DEFINITION ) + .value( "STANAG_4607_SEGMENT_TYPE_FREE_TEXT", + kas::STANAG_4607_SEGMENT_TYPE_FREE_TEXT ) + .value( "STANAG_4607_SEGMENT_TYPE_LOW_REFLECTIVITY_INDEX", + kas::STANAG_4607_SEGMENT_TYPE_LOW_REFLECTIVITY_INDEX ) + .value( "STANAG_4607_SEGMENT_TYPE_GROUP", + kas::STANAG_4607_SEGMENT_TYPE_GROUP ) + .value( "STANAG_4607_SEGMENT_TYPE_ATTACHED_TARGET", + kas::STANAG_4607_SEGMENT_TYPE_ATTACHED_TARGET ) + .value( "STANAG_4607_SEGMENT_TYPE_TEST_AND_STATUS", + kas::STANAG_4607_SEGMENT_TYPE_TEST_AND_STATUS ) + .value( "STANAG_4607_SEGMENT_TYPE_SYSTEM_SPECIFIC", + kas::STANAG_4607_SEGMENT_TYPE_SYSTEM_SPECIFIC ) + .value( "STANAG_4607_SEGMENT_TYPE_PROCESSING_HISTORY", + kas::STANAG_4607_SEGMENT_TYPE_PROCESSING_HISTORY ) + .value( "STANAG_4607_SEGMENT_TYPE_PLATFORM_LOCATION", + kas::STANAG_4607_SEGMENT_TYPE_PLATFORM_LOCATION ) + .value( "STANAG_4607_SEGMENT_TYPE_JOB_REQUEST", + kas::STANAG_4607_SEGMENT_TYPE_JOB_REQUEST ) + .value( "STANAG_4607_SEGMENT_TYPE_JOB_ACKNOWLEDGE", + kas::STANAG_4607_SEGMENT_TYPE_JOB_ACKNOWLEDGE ) + .value( "STANAG_4607_SEGMENT_TYPE_ENUM_END", + kas::STANAG_4607_SEGMENT_TYPE_ENUM_END ) + .def( "__str__", + []( kas::stanag_4607_segment_type const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_segment_header >( m, + "stanag_4607_segment_header" ) + .def( py::init( + []( kas::stanag_4607_segment_type& segment_type, + size_t& segment_size ){ + return kas::stanag_4607_segment_header{ segment_type, + segment_size }; + } ) + ) + .def_readwrite( "segment_type", + &kas::stanag_4607_segment_header::segment_type ) + .def_readwrite( "segment_size", + &kas::stanag_4607_segment_header::segment_size ) + .def( "__str__", + []( kas::stanag_4607_segment_header const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_segment_header_format >( m, + "stanag_4607_segment_header_format" ) + .def( py::init<>() ) + .def_property_readonly_static( "size", [](){ + return kas::stanag_4607_segment_header_format::size; + } ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_segment_header_format{}.read( ptr ); + } ); +} diff --git a/python/kwiver/arrows/stanag/segments/stanag_4607_segments.h b/python/kwiver/arrows/stanag/segments/stanag_4607_segments.h new file mode 100644 index 0000000000..890ec5e1ba --- /dev/null +++ b/python/kwiver/arrows/stanag/segments/stanag_4607_segments.h @@ -0,0 +1,19 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#ifndef KWIVER_PYTHON_ARROW_STANAG_4607_SEGMENTS_H_ +#define KWIVER_PYTHON_ARROW_STANAG_4607_SEGMENTS_H_ + +#include +#include + +#include + +namespace py = pybind11; + +namespace kas = kwiver::arrows::stanag; + +void stanag_4607_segments( py::module& m ); + +#endif diff --git a/python/kwiver/arrows/stanag/stanag_4607_packet.cxx b/python/kwiver/arrows/stanag/stanag_4607_packet.cxx new file mode 100644 index 0000000000..eda666a6a2 --- /dev/null +++ b/python/kwiver/arrows/stanag/stanag_4607_packet.cxx @@ -0,0 +1,203 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#include "stanag_4607_packet.h" + +using ptr_t = uint8_t const*; + +void +stanag_4607_packet( py::module& m ) +{ + py::enum_< kas::stanag_4607_security_classification >( m, + "stanag_4607_security_classification" ) + .value( "STANAG_4607_SECURITY_CLASS_TOP_SECRET", + kas::STANAG_4607_SECURITY_CLASS_TOP_SECRET ) + .value( "STANAG_4607_SECURITY_CLASS_SECRET", + kas::STANAG_4607_SECURITY_CLASS_SECRET ) + .value( "STANAG_4607_SECURITY_CLASS_CONFIDENTIAL", + kas::STANAG_4607_SECURITY_CLASS_CONFIDENTIAL ) + .value( "STANAG_4607_SECURITY_CLASS_RESTRICTED", + kas::STANAG_4607_SECURITY_CLASS_RESTRICTED ) + .value( "STANAG_4607_SECURITY_CLASS_UNCLASSIFIED", + kas::STANAG_4607_SECURITY_CLASS_UNCLASSIFIED ) + .value( "STANAG_4607_SECURITY_CLASS_ENUM_END", + kas::STANAG_4607_SECURITY_CLASS_ENUM_END ) + .def( "__str__", + []( kas::stanag_4607_security_classification const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::enum_< kas::stanag_4607_security_code >( m, "stanag_4607_security_code" ) + .value( "STANAG_4607_SECURITY_CODE_NONE", + kas::STANAG_4607_SECURITY_CODE_NONE ) + .value( "STANAG_4607_SECURITY_CODE_NOCONTRACT", + kas::STANAG_4607_SECURITY_CODE_NOCONTRACT ) + .value( "STANAG_4607_SECURITY_CODE_ORCON", + kas::STANAG_4607_SECURITY_CODE_ORCON ) + .value( "STANAG_4607_SECURITY_CODE_PROPIN", + kas::STANAG_4607_SECURITY_CODE_PROPIN ) + .value( "STANAG_4607_SECURITY_CODE_WNINTEL", + kas::STANAG_4607_SECURITY_CODE_WNINTEL ) + .value( "STANAG_4607_SECURITY_CODE_NATIONAL_ONLY", + kas::STANAG_4607_SECURITY_CODE_NATIONAL_ONLY ) + .value( "STANAG_4607_SECURITY_CODE_LIMDIS", + kas::STANAG_4607_SECURITY_CODE_LIMDIS ) + .value( "STANAG_4607_SECURITY_CODE_FOUO", + kas::STANAG_4607_SECURITY_CODE_FOUO ) + .value( "STANAG_4607_SECURITY_CODE_EFTO", + kas::STANAG_4607_SECURITY_CODE_EFTO ) + .value( "STANAG_4607_SECURITY_CODE_LIM_OFF_USE", + kas::STANAG_4607_SECURITY_CODE_LIM_OFF_USE ) + .value( "STANAG_4607_SECURITY_CODE_NONCOMPARTMENT", + kas::STANAG_4607_SECURITY_CODE_NONCOMPARTMENT ) + .value( "STANAG_4607_SECURITY_CODE_SPECIAL_CONTROL", + kas::STANAG_4607_SECURITY_CODE_SPECIAL_CONTROL ) + .value( "STANAG_4607_SECURITY_CODE_SPECIAL_INTEL", + kas::STANAG_4607_SECURITY_CODE_SPECIAL_INTEL ) + .value( "STANAG_4607_SECURITY_CODE_WARNING_NOTICE", + kas::STANAG_4607_SECURITY_CODE_WARNING_NOTICE ) + .value( "STANAG_4607_SECURITY_CODE_REL_NATO", + kas::STANAG_4607_SECURITY_CODE_REL_NATO ) + .value( "STANAG_4607_SECURITY_CODE_REL_4_EYES", + kas::STANAG_4607_SECURITY_CODE_REL_4_EYES ) + .value( "STANAG_4607_SECURITY_CODE_REL_9_EYES", + kas::STANAG_4607_SECURITY_CODE_REL_9_EYES ) + .value( "STANAG_4607_SECURITY_CODE_ENUM_END", + kas::STANAG_4607_SECURITY_CODE_ENUM_END ) + .def( "__str__", + []( kas::stanag_4607_security_code const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_packet_security >( m, + "stanag_4607_packet_security" ) + .def( py::init( + []( kas::stanag_4607_security_classification& classification, + std::string& class_system, + kas::stanag_4607_security_code& code){ + return kas::stanag_4607_packet_security{ classification, + class_system, code }; + } ) ) + .def_readwrite( "classification", + &kas::stanag_4607_packet_security::classification ) + .def_readwrite( "class_system", + &kas::stanag_4607_packet_security::class_system ) + .def_readwrite( "code", &kas::stanag_4607_packet_security::code ) + .def( "__str__", + []( kas::stanag_4607_packet_security const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::enum_< kas::stanag_4607_exercise_indicator >( m, + "stanag_4607_exercise_indicator" ) + .value( "STANAG_4607_EXERCISE_IND_OPERATION_REAL", + kas::STANAG_4607_EXERCISE_IND_OPERATION_REAL ) + .value( "STANAG_4607_EXERCISE_IND_OPERATION_SIMULATED", + kas::STANAG_4607_EXERCISE_IND_OPERATION_SIMULATED ) + .value( "STANAG_4607_EXERCISE_IND_OPERATION_SYNTHESIZED", + kas::STANAG_4607_EXERCISE_IND_OPERATION_SYNTHESIZED ) + .value( "STANAG_4607_EXERCISE_IND_EXERCISE_REAL", + kas::STANAG_4607_EXERCISE_IND_EXERCISE_REAL ) + .value( "STANAG_4607_EXERCISE_IND_EXERCISE_SIMULATED", + kas::STANAG_4607_EXERCISE_IND_EXERCISE_SIMULATED ) + .value( "STANAG_4607_EXERCISE_IND_EXERCISE_SYNTHESIZED", + kas::STANAG_4607_EXERCISE_IND_EXERCISE_SYNTHESIZED ) + .value( "STANAG_4607_EXERCISE_IND_ENUM_END", + kas::STANAG_4607_EXERCISE_IND_ENUM_END ) + .def( "__str__", + []( kas::stanag_4607_exercise_indicator const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_packet_header >( m, + "stanag_4607_packet_header" ) + .def( py::init( + []( std::string& version_id, size_t packet_size, + std::string& nationality, + kas::stanag_4607_packet_security& packet_security, + kas::stanag_4607_exercise_indicator exercise_indicator, + std::string& platform_id, int& mission_id, int& job_id ){ + return kas::stanag_4607_packet_header{ + version_id, packet_size, nationality, packet_security, + exercise_indicator, platform_id, mission_id, job_id }; + } ) ) + .def_readwrite( "version_id", &kas::stanag_4607_packet_header::version_id ) + .def_readwrite( "packet_size", + &kas::stanag_4607_packet_header::packet_size ) + .def_readwrite( "nationality", + &kas::stanag_4607_packet_header::nationality ) + .def_readwrite( "packet_security", + &kas::stanag_4607_packet_header::packet_security ) + .def_readwrite( "exercise_indicator", + &kas::stanag_4607_packet_header::exercise_indicator ) + .def_readwrite( "platform_id", + &kas::stanag_4607_packet_header::platform_id ) + .def_readwrite( "mission_id", &kas::stanag_4607_packet_header::mission_id ) + .def_readwrite( "job_id", &kas::stanag_4607_packet_header::job_id ) + .def( "__str__", + []( kas::stanag_4607_packet_header const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_packet_header_format >( m, + "stanag_4607_packet_header_format" ) + .def( py::init<>() ) + .def_property_readonly_static( "size", [](){ + return kas::stanag_4607_packet_header_format::size; + } ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_packet_header_format{}.read( ptr ); + } ); + + py::class_< kas::stanag_4607_packet >( m, "stanag_4607_packet" ) + .def_readwrite( "header", &kas::stanag_4607_packet::header ) + .def_readwrite( "segment_headers", + &kas::stanag_4607_packet::segment_headers ) + .def_property( "segments", + // getter + []( kas::stanag_4607_packet& self ){ + py::list buffer; + for( auto segment : self.segments ) + { + std::visit( [ buffer ]( const auto& x ){ + buffer.append( x ); + }, segment ); + } + return buffer; + }, + // setter + []( kas::stanag_4607_packet& self, + std::vector< kas::stanag_4607_segments > segments ){ + self.segments = segments; + } + ) + .def( "__str__", + []( kas::stanag_4607_packet const& value ){ + std::stringstream s; + s << value; + return s.str(); + } ); + + py::class_< kas::stanag_4607_packet_format >( m, + "stanag_4607_packet_format" ) + .def( py::init<>() ) + .def( "read", + []( ptr_t ptr ){ + return kas::stanag_4607_packet_format{}.read( ptr ); + } ); + + m.def( "read_stanag_4607_data", &kas::read_stanag_4607_data ); + m.def( "read_stanag_4607_file", &kas::read_stanag_4607_file ); +} diff --git a/python/kwiver/arrows/stanag/stanag_4607_packet.h b/python/kwiver/arrows/stanag/stanag_4607_packet.h new file mode 100644 index 0000000000..5ea8db76bc --- /dev/null +++ b/python/kwiver/arrows/stanag/stanag_4607_packet.h @@ -0,0 +1,19 @@ +// This file is part of KWIVER, and is distributed under the +// OSI-approved BSD 3-Clause License. See top-level LICENSE file or +// https://github.com/Kitware/kwiver/blob/master/LICENSE for details. + +#ifndef KWIVER_PYTHON_ARROW_STANAG_4607_PACKET_H_ +#define KWIVER_PYTHON_ARROW_STANAG_4607_PACKET_H_ + +#include +#include + +#include + +namespace py = pybind11; + +namespace kas = kwiver::arrows::stanag; + +void stanag_4607_packet( py::module& m ); + +#endif diff --git a/python/kwiver/arrows/stanag/stanag_module.cxx b/python/kwiver/arrows/stanag/stanag_module.cxx new file mode 100644 index 0000000000..91526b7cf4 --- /dev/null +++ b/python/kwiver/arrows/stanag/stanag_module.cxx @@ -0,0 +1,17 @@ +#include +#include + +#include +#include +#include +#include + +namespace py = pybind11; + +PYBIND11_MODULE( stanag, m ) +{ + stanag_4607_packet( m ); + stanag_4607_segments( m ); + stanag_4607_mission_segment( m ); + stanag_4607_dwell_segment( m ); +} From 1e7402ec68f233eceef26772bc776076f2646887 Mon Sep 17 00:00:00 2001 From: Hannah DeFazio Date: Tue, 14 Feb 2023 12:35:03 -0500 Subject: [PATCH 4/8] Be more specific with int types --- .../segments/stanag_4607_dwell_segment.cxx | 60 +++++++++---------- .../segments/stanag_4607_dwell_segment.h | 60 +++++++++---------- .../segments/stanag_4607_dwell_segment.cxx | 44 +++++++------- 3 files changed, 82 insertions(+), 82 deletions(-) diff --git a/arrows/stanag/segments/stanag_4607_dwell_segment.cxx b/arrows/stanag/segments/stanag_4607_dwell_segment.cxx index a76c47dad0..6bcea86125 100644 --- a/arrows/stanag/segments/stanag_4607_dwell_segment.cxx +++ b/arrows/stanag/segments/stanag_4607_dwell_segment.cxx @@ -99,9 +99,9 @@ ::read( ptr_t& ptr ) const { stanag_4607_sensor_pos_uncert result; - result.along_track = klv::klv_read_int< int >( ptr, (size_t)4 ); - result.cross_track = klv::klv_read_int< int >( ptr, (size_t)4 ); - result.altitude = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.along_track = klv::klv_read_int< uint32_t >( ptr, (size_t)4 ); + result.cross_track = klv::klv_read_int< uint32_t >( ptr, (size_t)4 ); + result.altitude = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); return result; } @@ -132,7 +132,7 @@ ::read( ptr_t& ptr ) const { stanag_4607_orientation result; - result.heading = klv::klv_read_flint< uint16_t >({0, 369.9945}, ptr, 2); + result.heading = klv::klv_read_flint< uint16_t >({0, 359.9945}, ptr, 2); result.pitch = klv::klv_read_flint< int16_t >({-90, 90}, ptr, 2); result.roll = klv::klv_read_flint< int16_t >({-90, 90}, ptr, 2); @@ -253,10 +253,10 @@ ::read( ptr_t& ptr ) const { stanag_4607_target_measure_uncert result; - result.slant_range = klv::klv_read_int< int >( ptr, (size_t)2 ); - result.cross_range = klv::klv_read_int< int >( ptr, (size_t)2 ); - result.height = klv::klv_read_int< int >( ptr, (size_t)1 ); - result.radial_velocity = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.slant_range = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); + result.cross_range = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); + result.height = klv::klv_read_int< uint8_t >( ptr, (size_t)1 ); + result.radial_velocity = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); return result; } @@ -285,8 +285,8 @@ ::read( ptr_t& ptr ) const { stanag_4607_truth_tag result; - result.application = klv::klv_read_int< int >( ptr, (size_t)1 ); - result.entity = klv::klv_read_int< int >( ptr, (size_t)4 ); + result.application = klv::klv_read_int< uint8_t >( ptr, (size_t)1 ); + result.entity = klv::klv_read_int< uint32_t >( ptr, (size_t)4 ); return result; } @@ -410,8 +410,8 @@ ::read( ptr_t& ptr, // Fields D32.4-D32.5 are conditional and always sent together // Condition: Sent if D32.2 and D32.3 are not sent else{ - result.delta_lat = klv::klv_read_int< int >( ptr, (size_t)2 ); - result.delta_long = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.delta_lat = klv::klv_read_int< int16_t >( ptr, (size_t)2 ); + result.delta_long = klv::klv_read_int< int16_t >( ptr, (size_t)2 ); } // Field D32.6 is optional @@ -419,7 +419,7 @@ ::read( ptr_t& ptr, STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_GEODETIC_HEIGHT) ) { - result.geodetic_height = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.geodetic_height = klv::klv_read_int< int16_t >( ptr, (size_t)2 ); } return result; @@ -541,7 +541,7 @@ ::read( ptr_t& ptr, if( existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_MTI_REPORT_IDX) ) { - result.mti_report_idx = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.mti_report_idx = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); } result.location = stanag_4607_target_location_format{} @@ -551,15 +551,15 @@ ::read( ptr_t& ptr, if( existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_VEL_LOS) ) { - result.velocity_los = klv::klv_read_int< int >( ptr, (size_t)2 ); - result.wrap_velocity = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.velocity_los = klv::klv_read_int< int16_t >( ptr, (size_t)2 ); + result.wrap_velocity = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); } // Field D32.9 is optional if( existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_SNR) ) { - result.snr = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.snr = klv::klv_read_int< int8_t >( ptr, (size_t)1 ); } // Field D32.10 is optional @@ -574,7 +574,7 @@ ::read( ptr_t& ptr, if( existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_CLASS_PROB) ) { - result.class_probability = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.class_probability = klv::klv_read_int< uint8_t >( ptr, (size_t)1 ); } // Fields D32.12-D32.15 are conditional and always sent together @@ -596,7 +596,7 @@ ::read( ptr_t& ptr, if( existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_RADAR_CROSS_SECT) ) { - result.radar_cross_sect = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.radar_cross_sect = klv::klv_read_int< int8_t >( ptr, (size_t)1 ); } return result; @@ -719,21 +719,21 @@ ::read( ptr_t& ptr ) const result.existence_mask = klv::bitfield_to_enums< stanag_4607_dwell_existence_mask_bit, uint64_t >( mask ); - result.revisit_index = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.revisit_index = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); - result.dwell_index = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.dwell_index = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); result.last_dwell_of_revisit = klv::klv_read_int< int >( ptr, (size_t)1 ); - result.target_report_count = klv::klv_read_int< int >( ptr, (size_t)2 ); + result.target_report_count = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); - result.dwell_time = klv::klv_read_int< int >( ptr, (size_t)4 ); + result.dwell_time = klv::klv_read_int< uint32_t >( ptr, (size_t)4 ); result.sensor_position.latitude = klv::klv_read_flint< int32_t >({-90, 90}, ptr, (size_t)4); result.sensor_position.longitude =klv::klv_read_flint< uint32_t >( {0, 359.999999916}, ptr, (size_t)4); - result.sensor_position.altitude = klv::klv_read_int< int >( ptr, (size_t)4 ); + result.sensor_position.altitude = klv::klv_read_int< int32_t >( ptr, (size_t)4 ); // Fields D10-11 are conditional and always sent together // Condition: Sent if D32.4 and D32.5 are sent @@ -758,17 +758,17 @@ ::read( ptr_t& ptr ) const { result.sensor_track = klv::klv_read_flint< uint16_t >({0, 359.9945}, ptr, 2); - result.sensor_speed = klv::klv_read_int< int >( ptr, (size_t)4 ); - result.sensor_vertical_vel = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.sensor_speed = klv::klv_read_int< uint32_t >( ptr, (size_t)4 ); + result.sensor_vertical_vel = klv::klv_read_int< int8_t >( ptr, (size_t)1 ); } // Fields D18-D20 are optional and always sent together if( result.existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK_UNCERT) ) { - result.sensor_track_uncert = klv::klv_read_int< int >( ptr, (size_t)1 ); - result.sensor_speed_uncert = klv::klv_read_int< int >( ptr, (size_t)2 ); - result.sensor_vertical_vel_uncert = klv::klv_read_int< int >( ptr, + result.sensor_track_uncert = klv::klv_read_int< uint8_t >( ptr, (size_t)1 ); + result.sensor_speed_uncert = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); + result.sensor_vertical_vel_uncert = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); } @@ -813,7 +813,7 @@ ::read( ptr_t& ptr ) const if( result.existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_MIN_DETECT_VEL) ) { - result.min_detectable_vel = klv::klv_read_int< int >( ptr, (size_t)1 ); + result.min_detectable_vel = klv::klv_read_int< uint8_t >( ptr, (size_t)1 ); } // Target reports diff --git a/arrows/stanag/segments/stanag_4607_dwell_segment.h b/arrows/stanag/segments/stanag_4607_dwell_segment.h index 42b50830d7..ac5a887929 100644 --- a/arrows/stanag/segments/stanag_4607_dwell_segment.h +++ b/arrows/stanag/segments/stanag_4607_dwell_segment.h @@ -39,7 +39,7 @@ struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_sensor_position { double latitude; double longitude; - int altitude; + int32_t altitude; }; // ---------------------------------------------------------------------------- @@ -84,9 +84,9 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_scale_factor_format /// the time of the dwell. Expressed in centimeters. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_sensor_pos_uncert { - int along_track; - int cross_track; - int altitude; + uint32_t along_track; + uint32_t cross_track; + uint16_t altitude; }; // ---------------------------------------------------------------------------- @@ -207,10 +207,10 @@ operator<<( std::ostream& os, /// Standard deviation of the target measurements. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_measure_uncert { - int slant_range; - int cross_range; - int height; - int radial_velocity; + uint16_t slant_range; + uint16_t cross_range; + uint8_t height; + uint16_t radial_velocity; }; // ---------------------------------------------------------------------------- @@ -236,8 +236,8 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_measure_uncert_format /// Information used to generate the MTI Target. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_truth_tag { - int application; - int entity; + uint8_t application; + uint32_t entity; }; // ---------------------------------------------------------------------------- @@ -326,9 +326,9 @@ struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_location { std::optional< double > hi_res_lat; std::optional< double > hi_res_long; - std::optional< int > delta_lat; - std::optional< int > delta_long; - std::optional< int > geodetic_height; + std::optional< int16_t > delta_lat; + std::optional< int16_t > delta_long; + std::optional< int16_t > geodetic_height; }; // ---------------------------------------------------------------------------- @@ -355,16 +355,16 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_location_format /// Each target observed within the dwell. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_report { - std::optional< int > mti_report_idx; + std::optional< uint16_t > mti_report_idx; std::optional< stanag_4607_target_location > location; - std::optional< int > velocity_los; - std::optional< int > wrap_velocity; - std::optional< int > snr; + std::optional< int16_t > velocity_los; + std::optional< uint16_t > wrap_velocity; + std::optional< int8_t > snr; std::optional< stanag_4607_target_classification > classification; - std::optional< int > class_probability; + std::optional< uint8_t > class_probability; std::optional< stanag_4607_target_measure_uncert > measurement_uncert; std::optional< stanag_4607_truth_tag > truth_tag; - std::optional< int > radar_cross_sect; + std::optional< int8_t > radar_cross_sect; }; // ---------------------------------------------------------------------------- @@ -398,24 +398,24 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_report_format struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_segment { std::set< stanag_4607_dwell_existence_mask_bit > existence_mask; - int revisit_index; - int dwell_index; + uint16_t revisit_index; + uint16_t dwell_index; int last_dwell_of_revisit; - int target_report_count; - int dwell_time; + uint16_t target_report_count; + uint32_t dwell_time; stanag_4607_sensor_position sensor_position; std::optional< stanag_4607_scale_factor > scale_factor; std::optional< stanag_4607_sensor_pos_uncert > sensor_pos_uncert; - std::optional< double > sensor_track; - std::optional< int > sensor_speed; - std::optional< int > sensor_vertical_vel; - std::optional< int > sensor_track_uncert; - std::optional< int > sensor_speed_uncert; - std::optional< int > sensor_vertical_vel_uncert; + std::optional< uint16_t > sensor_track; + std::optional< uint32_t > sensor_speed; + std::optional< int8_t > sensor_vertical_vel; + std::optional< uint8_t > sensor_track_uncert; + std::optional< uint16_t > sensor_speed_uncert; + std::optional< uint16_t > sensor_vertical_vel_uncert; std::optional< stanag_4607_orientation > platform_orient; stanag_4607_dwell_area dwell_area; std::optional< stanag_4607_orientation > sensor_orientation; - std::optional< int > min_detectable_vel; + std::optional< uint8_t > min_detectable_vel; std::vector< stanag_4607_target_report > target_reports; }; diff --git a/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx b/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx index e312599eec..4a2a2df5cc 100644 --- a/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx +++ b/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx @@ -13,7 +13,7 @@ stanag_4607_dwell_segment( py::module& m ) { py::class_< kas::stanag_4607_sensor_position >( m, "stanag_4607_sensor_position" ) - .def( py::init( []( double latitude, double longitude, int altitude){ + .def( py::init( []( double latitude, double longitude, int32_t altitude){ return kas::stanag_4607_sensor_position{ latitude, longitude, altitude }; @@ -52,7 +52,7 @@ stanag_4607_dwell_segment( py::module& m ) py::class_< kas::stanag_4607_sensor_pos_uncert >( m, "stanag_4607_sensor_pos_uncert" ) - .def( py::init( []( int along_track, int cross_track, int altitude ){ + .def( py::init( []( uint32_t along_track, uint32_t cross_track, uint16_t altitude ){ return kas::stanag_4607_sensor_pos_uncert{ along_track, cross_track, altitude }; @@ -200,8 +200,8 @@ stanag_4607_dwell_segment( py::module& m ) py::class_< kas::stanag_4607_target_measure_uncert >( m, "stanag_4607_target_measure_uncert" ) - .def( py::init( []( int slant_range, int cross_range, int height, - int radial_velocity ){ + .def( py::init( []( uint16_t slant_range, uint16_t cross_range, uint8_t height, + uint16_t radial_velocity ){ return kas::stanag_4607_target_measure_uncert{ slant_range, cross_range, height, radial_velocity }; } ) ) @@ -228,7 +228,7 @@ stanag_4607_dwell_segment( py::module& m ) } ); py::class_< kas::stanag_4607_truth_tag >( m, "stanag_4607_truth_tag" ) - .def( py::init( []( int application, int entity ){ + .def( py::init( []( uint8_t application, uint32_t entity ){ return kas::stanag_4607_truth_tag{ application, entity }; } ) ) .def_readwrite( "application", &kas::stanag_4607_truth_tag::application ) @@ -364,8 +364,8 @@ stanag_4607_dwell_segment( py::module& m ) py::class_< kas::stanag_4607_target_location >( m, "stanag_4607_target_location" ) - .def( py::init( []( double hi_res_lat, double hi_res_long, int delta_lat, - int delta_long, int geodetic_height ){ + .def( py::init( []( double hi_res_lat, double hi_res_long, int16_t delta_lat, + int16_t delta_long, int16_t geodetic_height ){ return kas::stanag_4607_target_location{ hi_res_lat, hi_res_long, delta_lat, @@ -401,19 +401,19 @@ stanag_4607_dwell_segment( py::module& m ) py::class_< kas::stanag_4607_target_report >( m, "stanag_4607_target_report" ) - .def( py::init( [](std::optional< int > mti_report_idx, + .def( py::init( [](std::optional< uint16_t > mti_report_idx, std::optional< kas::stanag_4607_target_location > location, - std::optional< int > velocity_los, - std::optional< int > wrap_velocity, - std::optional< int > snr, + std::optional< int16_t > velocity_los, + std::optional< uint16_t > wrap_velocity, + std::optional< int8_t > snr, std::optional< kas::stanag_4607_target_classification > classification, - std::optional< int > class_probability, + std::optional< uint8_t > class_probability, std::optional< kas::stanag_4607_target_measure_uncert > measurement_uncert, std::optional< kas::stanag_4607_truth_tag > truth_tag, - std::optional< int > radar_cross_sect ){ + std::optional< int8_t > radar_cross_sect ){ auto result = kas::stanag_4607_target_report{}; if( mti_report_idx.has_value() ) @@ -495,26 +495,26 @@ stanag_4607_dwell_segment( py::module& m ) "stanag_4607_dwell_segment" ) .def( py::init( []( std::set< kas::stanag_4607_dwell_existence_mask_bit > existence_mask, - int revisit_index, int dwell_index, + uint16_t revisit_index, uint16_t dwell_index, int last_dwell_of_revisit, - int target_report_count, int dwell_time, + uint16_t target_report_count, uint32_t dwell_time, kas::stanag_4607_sensor_position sensor_position, std::optional< kas::stanag_4607_scale_factor > scale_factor, std::optional< kas::stanag_4607_sensor_pos_uncert > sensor_pos_uncert, - std::optional< double > sensor_track, - std::optional< int > sensor_speed, - std::optional< int > sensor_vertical_vel, - std::optional< int > sensor_track_uncert, - std::optional< int > sensor_speed_uncert, - std::optional< int > sensor_vertical_vel_uncert, + std::optional< uint16_t > sensor_track, + std::optional< uint32_t > sensor_speed, + std::optional< int8_t > sensor_vertical_vel, + std::optional< uint8_t > sensor_track_uncert, + std::optional< uint16_t > sensor_speed_uncert, + std::optional< uint16_t > sensor_vertical_vel_uncert, std::optional< kas::stanag_4607_orientation > platform_orient, kas::stanag_4607_dwell_area dwell_area, std::optional< kas::stanag_4607_orientation > sensor_orientation, - std::optional< int > min_detectable_vel, + std::optional< uint8_t > min_detectable_vel, std::vector< kas::stanag_4607_target_report > target_reports ){ auto result = kas::stanag_4607_dwell_segment{}; From 6c2f1f177a01093be945ec0b6a39b8fa65b9647a Mon Sep 17 00:00:00 2001 From: Hannah DeFazio Date: Wed, 15 Feb 2023 12:18:11 -0500 Subject: [PATCH 5/8] Read [signed]binary angles via SA and BA definitions in standard --- .../segments/stanag_4607_dwell_segment.cxx | 56 +++++++++++-------- .../segments/stanag_4607_dwell_segment.h | 36 +++++------- arrows/stanag/stanag_util.cxx | 13 +++++ arrows/stanag/stanag_util.h | 12 ++++ .../segments/stanag_4607_dwell_segment.cxx | 12 ++-- 5 files changed, 77 insertions(+), 52 deletions(-) diff --git a/arrows/stanag/segments/stanag_4607_dwell_segment.cxx b/arrows/stanag/segments/stanag_4607_dwell_segment.cxx index 6bcea86125..270cc3e2d0 100644 --- a/arrows/stanag/segments/stanag_4607_dwell_segment.cxx +++ b/arrows/stanag/segments/stanag_4607_dwell_segment.cxx @@ -66,8 +66,10 @@ ::read( ptr_t& ptr ) const { stanag_4607_scale_factor result; - result.lat_scale = klv::klv_read_int< int >( ptr, (size_t)4 ); - result.long_scale = klv::klv_read_int< int >( ptr, (size_t)4 ); + result.lat_scale = float_to_signed_binary_angle( float( + klv::klv_read_int< int32_t >( ptr, (size_t)4 ) ), 32 ); + result.long_scale = float_to_binary_angle( float( + klv::klv_read_int< uint32_t >( ptr, (size_t)4 ) ), 32 ); return result; @@ -132,9 +134,12 @@ ::read( ptr_t& ptr ) const { stanag_4607_orientation result; - result.heading = klv::klv_read_flint< uint16_t >({0, 359.9945}, ptr, 2); - result.pitch = klv::klv_read_flint< int16_t >({-90, 90}, ptr, 2); - result.roll = klv::klv_read_flint< int16_t >({-90, 90}, ptr, 2); + result.heading = float_to_binary_angle( float( + klv::klv_read_int< uint16_t >(ptr, 2) ), 16); + result.pitch = float_to_signed_binary_angle( float( + klv::klv_read_int< int16_t >(ptr, 2) ), 16); + result.roll = float_to_signed_binary_angle( float( + klv::klv_read_int< int16_t >(ptr, 2) ), 16); return result; } @@ -403,9 +408,10 @@ ::read( ptr_t& ptr, if( existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_TARGET_REPORT_LOCATION_HI_RES_LAT) ) { - result.hi_res_lat = klv::klv_read_flint< int32_t >({-90, 90}, ptr, 4); - result.hi_res_long = klv::klv_read_flint< uint32_t >({0, 359.999999916}, - ptr, 4); + result.hi_res_lat = float_to_signed_binary_angle( float( + klv::klv_read_int< int32_t >(ptr, (size_t)4) ), 32); + result.hi_res_long = float_to_binary_angle( float( + klv::klv_read_int< uint32_t >(ptr, (size_t)4) ), 32); } // Fields D32.4-D32.5 are conditional and always sent together // Condition: Sent if D32.2 and D32.3 are not sent @@ -729,11 +735,12 @@ ::read( ptr_t& ptr ) const result.dwell_time = klv::klv_read_int< uint32_t >( ptr, (size_t)4 ); - result.sensor_position.latitude = klv::klv_read_flint< int32_t >({-90, 90}, - ptr, (size_t)4); - result.sensor_position.longitude =klv::klv_read_flint< uint32_t >( - {0, 359.999999916}, ptr, (size_t)4); - result.sensor_position.altitude = klv::klv_read_int< int32_t >( ptr, (size_t)4 ); + result.sensor_position.latitude = float_to_signed_binary_angle( float( + klv::klv_read_int< int32_t >(ptr, (size_t)4) ), 32 ); + result.sensor_position.longitude = float_to_binary_angle( float( + klv::klv_read_int< uint32_t >(ptr, (size_t)4)), 32 ); + result.sensor_position.altitude = klv::klv_read_int< int32_t >( ptr, + (size_t)4 ); // Fields D10-11 are conditional and always sent together // Condition: Sent if D32.4 and D32.5 are sent @@ -756,8 +763,8 @@ ::read( ptr_t& ptr ) const if( result.existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK) ) { - result.sensor_track = klv::klv_read_flint< uint16_t >({0, 359.9945}, - ptr, 2); + result.sensor_track = float_to_binary_angle( float( + klv::klv_read_int< uint16_t >( ptr, (size_t)2) ), 16 ); result.sensor_speed = klv::klv_read_int< uint32_t >( ptr, (size_t)4 ); result.sensor_vertical_vel = klv::klv_read_int< int8_t >( ptr, (size_t)1 ); } @@ -766,8 +773,10 @@ ::read( ptr_t& ptr ) const if( result.existence_mask.count( STANAG_4607_DWELL_EXIST_MASK_BIT_SENSOR_TRACK_UNCERT) ) { - result.sensor_track_uncert = klv::klv_read_int< uint8_t >( ptr, (size_t)1 ); - result.sensor_speed_uncert = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); + result.sensor_track_uncert = klv::klv_read_int< uint8_t >( ptr, + (size_t)1 ); + result.sensor_speed_uncert = klv::klv_read_int< uint16_t >( ptr, + (size_t)2 ); result.sensor_vertical_vel_uncert = klv::klv_read_int< uint16_t >( ptr, (size_t)2 ); } @@ -781,10 +790,10 @@ ::read( ptr_t& ptr ) const } // Fields D24-27 are mandatory - result.dwell_area.center_lat = klv::klv_read_flint< int32_t >({-90, 90}, - ptr, 4); - result.dwell_area.center_long = klv::klv_read_flint< uint32_t >( - {0, 359.999979}, ptr, 4); + result.dwell_area.center_lat = float_to_signed_binary_angle( float( + klv::klv_read_int< int32_t >(ptr, (size_t)4) ), 32); + result.dwell_area.center_long = float_to_binary_angle( float( + klv::klv_read_int< uint32_t >(ptr, (size_t)4) ), 32); kwiver::vital::interval interval = {0, 255.9928}; size_t length = 2; @@ -794,8 +803,9 @@ ::read( ptr_t& ptr ) const result.dwell_area.range_half_ext = v * scale + interval.lower(); - result.dwell_area.dwell_angle_half_ext = klv::klv_read_flint< uint16_t >( - {0, 359.9945}, ptr, 2); + result.dwell_area.dwell_angle_half_ext = float_to_binary_angle( float( + klv::klv_read_int< uint16_t >(ptr, + (size_t)2) ), 16); // Fields D28-D30 are optional // If at least one is sent, any omitted fields are set to 0 diff --git a/arrows/stanag/segments/stanag_4607_dwell_segment.h b/arrows/stanag/segments/stanag_4607_dwell_segment.h index ac5a887929..2cc41c96cc 100644 --- a/arrows/stanag/segments/stanag_4607_dwell_segment.h +++ b/arrows/stanag/segments/stanag_4607_dwell_segment.h @@ -18,11 +18,11 @@ #include #include #include +#include #include #include #include #include -#include namespace kwiver { @@ -32,13 +32,12 @@ namespace stanag { namespace kv = kwiver::vital; - // ---------------------------------------------------------------------------- /// Position of the sensor at the temporal center of the dwell struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_sensor_position { - double latitude; - double longitude; + float latitude; + float longitude; int32_t altitude; }; @@ -56,8 +55,8 @@ DECLARE_STANAG_CMP( stanag_4607_sensor_position ) /// Report. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_scale_factor { - int lat_scale; - int long_scale; + float lat_scale; + float long_scale; }; // ---------------------------------------------------------------------------- @@ -78,7 +77,6 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_scale_factor_format read( ptr_t& ptr ) const; }; - // ---------------------------------------------------------------------------- /// Estimate of the standard deviation in the estimated sensor location at /// the time of the dwell. Expressed in centimeters. @@ -107,7 +105,6 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_sensor_pos_uncert_format read( ptr_t& ptr ) const; }; - // ---------------------------------------------------------------------------- /// The toll angle of the platform at the time of the dwell. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_orientation @@ -135,15 +132,14 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_orientation_format read( ptr_t& ptr ) const; }; - // ---------------------------------------------------------------------------- /// The position of the center of the dwell area struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_area { - double center_lat; - double center_long; - double range_half_ext; - double dwell_angle_half_ext; + float center_lat; + float center_long; + float range_half_ext; + float dwell_angle_half_ext; }; // ---------------------------------------------------------------------------- @@ -151,7 +147,6 @@ KWIVER_ALGO_STANAG_EXPORT std::ostream& operator<<( std::ostream& os, stanag_4607_dwell_area const& value ); - // ---------------------------------------------------------------------------- DECLARE_STANAG_CMP( stanag_4607_dwell_area ) @@ -231,7 +226,6 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_measure_uncert_format read( ptr_t& ptr ) const; }; - // ---------------------------------------------------------------------------- /// Information used to generate the MTI Target. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_truth_tag @@ -258,7 +252,6 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_truth_tag_format read( ptr_t& ptr ) const; }; - // ---------------------------------------------------------------------------- /// Each bit of the Existence Mask indicates whether or not the corresponding /// field of the Dwell Segment is present in the data stream. @@ -324,8 +317,8 @@ operator<<( std::ostream& os, /// The position of the reported detection. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_location { - std::optional< double > hi_res_lat; - std::optional< double > hi_res_long; + std::optional< float > hi_res_lat; + std::optional< float > hi_res_long; std::optional< int16_t > delta_lat; std::optional< int16_t > delta_long; std::optional< int16_t > geodetic_height; @@ -350,7 +343,6 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_location_format std::set< stanag_4607_dwell_existence_mask_bit > existence_mask ) const; }; - // ---------------------------------------------------------------------------- /// Each target observed within the dwell. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_report @@ -389,10 +381,9 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_target_report_format stanag_4607_target_report read( ptr_t& ptr, - std::set< stanag_4607_dwell_existence_mask_bit > existence_mask ) const; + std::set< stanag_4607_dwell_existence_mask_bit > existence_mask ) const; }; - // ---------------------------------------------------------------------------- /// A report on a grouping of zero or more target reports. struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_segment @@ -406,7 +397,7 @@ struct KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_segment stanag_4607_sensor_position sensor_position; std::optional< stanag_4607_scale_factor > scale_factor; std::optional< stanag_4607_sensor_pos_uncert > sensor_pos_uncert; - std::optional< uint16_t > sensor_track; + std::optional< float > sensor_track; std::optional< uint32_t > sensor_speed; std::optional< int8_t > sensor_vertical_vel; std::optional< uint8_t > sensor_track_uncert; @@ -434,7 +425,6 @@ class KWIVER_ALGO_STANAG_EXPORT stanag_4607_dwell_segment_format public: stanag_4607_dwell_segment_format(); - size_t size; stanag_4607_dwell_segment diff --git a/arrows/stanag/stanag_util.cxx b/arrows/stanag/stanag_util.cxx index f49cd2d46d..abbce29040 100644 --- a/arrows/stanag/stanag_util.cxx +++ b/arrows/stanag/stanag_util.cxx @@ -25,6 +25,19 @@ trim_whitespace( std::string input ) return input.substr( str_begin, ( str_end - str_begin ) + 1 ); } +// ---------------------------------------------------------------------------- +float +float_to_binary_angle( float value, int n ) +{ + return value * 1.40625 * ( 1 / pow( 2, n - 8 ) ); +} + +// ---------------------------------------------------------------------------- +float +float_to_signed_binary_angle( float value, int n ) +{ + return value * 1.40625 * ( 1 / pow( 2, n - 7 ) ); +} } // namespace stanag diff --git a/arrows/stanag/stanag_util.h b/arrows/stanag/stanag_util.h index 984e5069df..ecd88e7325 100644 --- a/arrows/stanag/stanag_util.h +++ b/arrows/stanag/stanag_util.h @@ -131,6 +131,18 @@ KWIVER_ALGO_STANAG_EXPORT std::string trim_whitespace( std::string input ); +// ---------------------------------------------------------------------------- +/// Convert a floating point number to a binary angle +KWIVER_ALGO_STANAG_EXPORT +float +float_to_binary_angle( float value, int n ); + +// ---------------------------------------------------------------------------- +/// Convert a floating point number to a signed binary angle +KWIVER_ALGO_STANAG_EXPORT +float +float_to_signed_binary_angle( float value, int n ); + } // namespace stanag } // namespace arrows diff --git a/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx b/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx index 4a2a2df5cc..5b80126426 100644 --- a/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx +++ b/python/kwiver/arrows/stanag/segments/stanag_4607_dwell_segment.cxx @@ -13,7 +13,7 @@ stanag_4607_dwell_segment( py::module& m ) { py::class_< kas::stanag_4607_sensor_position >( m, "stanag_4607_sensor_position" ) - .def( py::init( []( double latitude, double longitude, int32_t altitude){ + .def( py::init( []( float latitude, float longitude, int32_t altitude){ return kas::stanag_4607_sensor_position{ latitude, longitude, altitude }; @@ -29,7 +29,7 @@ stanag_4607_dwell_segment( py::module& m ) } ); py::class_< kas::stanag_4607_scale_factor >( m, "stanag_4607_scale_factor" ) - .def( py::init( []( int lat_scale, int long_scale ){ + .def( py::init( []( float lat_scale, float long_scale ){ return kas::stanag_4607_scale_factor{ lat_scale, long_scale }; } ) ) @@ -101,8 +101,8 @@ stanag_4607_dwell_segment( py::module& m ) } ); py::class_< kas::stanag_4607_dwell_area >( m, "stanag_4607_dwell_area" ) - .def( py::init( []( double center_lat, double center_long, - double range_half_ext, double dwell_angle_half_ext ){ + .def( py::init( []( float center_lat, float center_long, + float range_half_ext, float dwell_angle_half_ext ){ return kas::stanag_4607_dwell_area{ center_lat, center_long, range_half_ext, @@ -364,7 +364,7 @@ stanag_4607_dwell_segment( py::module& m ) py::class_< kas::stanag_4607_target_location >( m, "stanag_4607_target_location" ) - .def( py::init( []( double hi_res_lat, double hi_res_long, int16_t delta_lat, + .def( py::init( []( float hi_res_lat, float hi_res_long, int16_t delta_lat, int16_t delta_long, int16_t geodetic_height ){ return kas::stanag_4607_target_location{ hi_res_lat, hi_res_long, @@ -503,7 +503,7 @@ stanag_4607_dwell_segment( py::module& m ) scale_factor, std::optional< kas::stanag_4607_sensor_pos_uncert > sensor_pos_uncert, - std::optional< uint16_t > sensor_track, + std::optional< float > sensor_track, std::optional< uint32_t > sensor_speed, std::optional< int8_t > sensor_vertical_vel, std::optional< uint8_t > sensor_track_uncert, From 666bbc5ea8fe2e035f02d6667ee7e1c66a653fa4 Mon Sep 17 00:00:00 2001 From: Hannah DeFazio Date: Thu, 16 Feb 2023 10:16:40 -0500 Subject: [PATCH 6/8] bug fix: height was not printing in python --- arrows/stanag/segments/stanag_4607_dwell_segment.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrows/stanag/segments/stanag_4607_dwell_segment.cxx b/arrows/stanag/segments/stanag_4607_dwell_segment.cxx index 270cc3e2d0..f2437345c5 100644 --- a/arrows/stanag/segments/stanag_4607_dwell_segment.cxx +++ b/arrows/stanag/segments/stanag_4607_dwell_segment.cxx @@ -237,7 +237,7 @@ operator<<( std::ostream& os, stanag_4607_target_measure_uncert const& value ) return os << "{ " << "Slant Range: " << value.slant_range << " cm" << ", " << "Cross Range: " << value.cross_range << " dm" << ", " - << "Height: " << value.height << " m" << ", " + << "Height: " << int(value.height) << " m" << ", " << "Target Radial Velocity: " << value.radial_velocity << " cm/sec" << " }"; From 6d1bf8677c3399ffde60722f48d4c036eebeea3b Mon Sep 17 00:00:00 2001 From: Hannah DeFazio Date: Thu, 16 Feb 2023 12:12:42 -0500 Subject: [PATCH 7/8] Remove extra imports --- arrows/stanag/segments/stanag_4607_dwell_segment.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arrows/stanag/segments/stanag_4607_dwell_segment.h b/arrows/stanag/segments/stanag_4607_dwell_segment.h index 2cc41c96cc..e3c9f8c7f0 100644 --- a/arrows/stanag/segments/stanag_4607_dwell_segment.h +++ b/arrows/stanag/segments/stanag_4607_dwell_segment.h @@ -12,9 +12,6 @@ #include #include -#include -#include - #include #include #include From b1f4d0fe448a1bdfac187b03f13a82d7589bd1da Mon Sep 17 00:00:00 2001 From: Hannah DeFazio Date: Mon, 20 Feb 2023 14:21:37 -0500 Subject: [PATCH 8/8] Fix bug in docker --- python/kwiver/arrows/stanag/stanag_4607_packet.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/kwiver/arrows/stanag/stanag_4607_packet.cxx b/python/kwiver/arrows/stanag/stanag_4607_packet.cxx index eda666a6a2..394db99df6 100644 --- a/python/kwiver/arrows/stanag/stanag_4607_packet.cxx +++ b/python/kwiver/arrows/stanag/stanag_4607_packet.cxx @@ -171,7 +171,7 @@ stanag_4607_packet( py::module& m ) py::list buffer; for( auto segment : self.segments ) { - std::visit( [ buffer ]( const auto& x ){ + std::visit( [ &buffer ]( auto& x ){ buffer.append( x ); }, segment ); }