From 9b17824c49577afc33e184358d8e5262cfee4927 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 17 Sep 2019 14:13:51 -0700 Subject: [PATCH] Big update to UHD 3.14, Gnuradio 3.8, Python 3.6. Not fully tested. --- CMakeLists.txt | 131 ++--- apps/modes_gui | 4 +- apps/modes_rx | 5 +- cmake/Modules/CMakeParseArgumentsCopy.cmake | 2 +- cmake/Modules/FindGnuradioRuntime.cmake | 36 -- cmake/Modules/FindPyQt.py | 24 - cmake/Modules/FindPyQt4.cmake | 61 --- cmake/Modules/FindQwt.cmake | 41 -- cmake/Modules/GrBoost.cmake | 99 ---- cmake/Modules/GrMiscUtils.cmake | 210 -------- cmake/Modules/GrPlatform.cmake | 54 --- cmake/Modules/GrPython.cmake | 232 --------- cmake/Modules/GrSwig.cmake | 232 --------- cmake/Modules/GrTest.cmake | 137 ------ cmake/Modules/air_modesConfig.cmake | 31 ++ cmake/Modules/targetConfig.cmake.in | 26 + lib/CMakeLists.txt | 41 +- python/CMakeLists.txt | 2 +- python/__init__.py | 60 +-- python/altitude.py | 213 ++++---- python/az_map.py | 1 - python/cpr.py | 512 ++++++++++---------- python/flightgear.py | 8 +- python/mlat.py | 19 +- python/mlat_types.py | 1 - python/{types.py => modes_types.py} | 0 python/msprint.py | 3 +- python/parse.py | 25 +- python/qa_gr-air-modes.py | 59 --- python/radio.py | 26 +- python/raw_server.py | 5 +- python/rx_path.py | 1 - python/sbs1.py | 5 +- python/sql.py | 1 - python/zmq_socket.py | 6 +- swig/CMakeLists.txt | 7 +- 36 files changed, 590 insertions(+), 1730 deletions(-) delete mode 100644 cmake/Modules/FindGnuradioRuntime.cmake delete mode 100644 cmake/Modules/FindPyQt.py delete mode 100644 cmake/Modules/FindPyQt4.cmake delete mode 100644 cmake/Modules/FindQwt.cmake delete mode 100644 cmake/Modules/GrBoost.cmake delete mode 100644 cmake/Modules/GrMiscUtils.cmake delete mode 100644 cmake/Modules/GrPlatform.cmake delete mode 100644 cmake/Modules/GrPython.cmake delete mode 100644 cmake/Modules/GrSwig.cmake delete mode 100644 cmake/Modules/GrTest.cmake create mode 100644 cmake/Modules/air_modesConfig.cmake create mode 100644 cmake/Modules/targetConfig.cmake.in delete mode 100644 python/mlat_types.py rename python/{types.py => modes_types.py} (100%) delete mode 100755 python/qa_gr-air-modes.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ede330..4df8ba0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,12 +21,16 @@ ######################################################################## # Project setup ######################################################################## -cmake_minimum_required(VERSION 2.6) -project(gr-gr-air-modes CXX C) -set(gr-gr-air-modes_VERSION_MAJOR 0) -set(gr-gr-air-modes_VERSION_MINOR 0) +cmake_minimum_required(VERSION 3.8) +project(gr-air-modes CXX C) enable_testing() +#install to PyBOMBS target prefix if defined +if(DEFINED ENV{PYBOMBS_PREFIX}) + set(CMAKE_INSTALL_PREFIX $ENV{PYBOMBS_PREFIX}) + message(STATUS "PyBOMBS installed GNU Radio. Setting CMAKE_INSTALL_PREFIX to $ENV{PYBOMBS_PREFIX}") +endif() + #select the release build type by default to get optimization flags if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") @@ -34,76 +38,91 @@ if(NOT CMAKE_BUILD_TYPE) endif(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) +#make sure our local CMake Modules path comes first +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) + +# Set the version information here +set(VERSION_MAJOR 1) +set(VERSION_API 0) +set(VERSION_ABI 0) +set(VERSION_PATCH git) + +# Set cmake policies. +# This will suppress developer warnings during the cmake process that can occur +# if a newer cmake version than the minimum is used. +cmake_policy(SET CMP0011 NEW) + +# Enable generation of compile_commands.json for code completion engines +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) ######################################################################## # Compiler specific setup ######################################################################## -if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32) +if((CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR + CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + AND NOT WIN32) #http://gcc.gnu.org/wiki/Visibility add_definitions(-fvisibility=hidden) endif() -######################################################################## -# Find boost -######################################################################## -include(GrBoost) - -find_package(PythonLibs 2) +IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + SET(CMAKE_CXX_STANDARD 11) +ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + SET(CMAKE_CXX_STANDARD 11) +ELSEIF(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + SET(CMAKE_CXX_STANDARD 11) +ELSE() + message(WARNING "C++ standard could not be set because compiler is not GNU, Clang or MSVC.") +ENDIF() + +IF(CMAKE_C_COMPILER_ID STREQUAL "GNU") + SET(CMAKE_C_STANDARD 11) +ELSEIF(CMAKE_C_COMPILER_ID MATCHES "Clang") + SET(CMAKE_C_STANDARD 11) +ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "MSVC") + SET(CMAKE_C_STANDARD 11) +ELSE() + message(WARNING "C standard could not be set because compiler is not GNU, Clang or MSVC.") +ENDIF() ######################################################################## -# Install directories +# Find gnuradio build dependencies ######################################################################## +find_package(Gnuradio "3.8" REQUIRED) +include(GrVersion) + include(GrPlatform) #define LIB_SUFFIX -set(GR_RUNTIME_DIR bin) -set(GR_LIBRARY_DIR lib${LIB_SUFFIX}) -set(GR_INCLUDE_DIR include) -set(GR_DATA_DIR share) + +if(NOT CMAKE_MODULES_DIR) + set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake) +endif(NOT CMAKE_MODULES_DIR) + +set(GR_INCLUDE_DIR include/foo) +set(GR_CMAKE_DIR ${CMAKE_MODULES_DIR}/foo) set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME}) -set(GR_DOC_DIR ${GR_DATA_DIR}/doc) set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME}) -set(GR_CONF_DIR etc) set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d) -set(GR_LIBEXEC_DIR libexec) set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME}) -set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks) - -######################################################################## -# Find gnuradio build dependencies -######################################################################## -set(GR_REQUIRED_COMPONENTS RUNTIME) -find_package(Gnuradio "3.7.2" REQUIRED) -if(NOT GNURADIO_RUNTIME_FOUND) - message(FATAL_ERROR "GnuRadio Runtime required to compile gr-air-modes") -endif() - -######################################################################## -# Find PyZMQ bindings ######################################################################## -include(GrPython) -#GR_PYTHON_CHECK_MODULE("PyZMQ" "zmq" "int(zmq.__version__.split('.')[0]) >= 13" PYZMQ_FOUND) -#if(NOT PYZMQ_FOUND) -# message(FATAL_ERROR "Python ZMQ bindings not found.") -#endif() - -######################################################################## -# Setup the include and linker paths -######################################################################## -include_directories( - ${CMAKE_SOURCE_DIR}/include - ${Boost_INCLUDE_DIRS} - ${GNURADIO_RUNTIME_INCLUDE_DIRS} -) - -link_directories( - ${Boost_LIBRARY_DIRS} - ${GNURADIO_RUNTIME_LIBRARY_DIRS} -) - -# Set component parameters -set(GR_GR-AIR-MODES_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "" FORCE) -set(GR_GR-AIR-MODES_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/swig CACHE INTERNAL "" FORCE) +# On Apple only, set install name and use rpath correctly, if not already set +######################################################################## +if(APPLE) + if(NOT CMAKE_INSTALL_NAME_DIR) + set(CMAKE_INSTALL_NAME_DIR + ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE + PATH "Library Install Name Destination Directory" FORCE) + endif(NOT CMAKE_INSTALL_NAME_DIR) + if(NOT CMAKE_INSTALL_RPATH) + set(CMAKE_INSTALL_RPATH + ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE + PATH "Library Install RPath" FORCE) + endif(NOT CMAKE_INSTALL_RPATH) + if(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE + BOOL "Do Build Using Library Install RPath" FORCE) + endif(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) +endif(APPLE) ######################################################################## # Create uninstall target diff --git a/apps/modes_gui b/apps/modes_gui index e39c88b..936282b 100755 --- a/apps/modes_gui +++ b/apps/modes_gui @@ -372,7 +372,7 @@ class mainwindow(QtGui.QMainWindow): self._htmlfile.flush() class WebPage(QtWebKit.QWebPage): def javaScriptConsoleMessage(self, msg, line, source): - print '%s line %d: %s' % (source, line, msg) + print('%s line %d: %s' % (source, line, msg)) page = WebPage() self.ui.mapView.setPage(page) self.ui.mapView.load( QtCore.QUrl( QtCore.QUrl.fromLocalFile("/tmp/mode_s.html") ) ) @@ -485,7 +485,7 @@ class mainwindow(QtGui.QMainWindow): for item in prefs.items("GUI"): defaults[item[0]] = item[1] except (IOError, ConfigParser.NoSectionError): - print "No preferences file %s found, creating..." % os.path.expanduser(self.opt_file) + print("No preferences file %s found, creating..." % os.path.expanduser(self.opt_file)) self.write_defaults(defaults) return defaults diff --git a/apps/modes_rx b/apps/modes_rx index 24de121..5db2e72 100755 --- a/apps/modes_rx +++ b/apps/modes_rx @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2010, 2013 Nick Foster # # This file is part of gr-air-modes @@ -23,9 +23,8 @@ from gnuradio.eng_option import eng_option from gnuradio.gr.pubsub import pubsub from optparse import OptionParser import time, os, sys, threading, math -from string import split, join import air_modes -from air_modes.types import * +from air_modes.modes_types import * from air_modes.exceptions import * import zmq diff --git a/cmake/Modules/CMakeParseArgumentsCopy.cmake b/cmake/Modules/CMakeParseArgumentsCopy.cmake index 7ce4c49..66016cb 100644 --- a/cmake/Modules/CMakeParseArgumentsCopy.cmake +++ b/cmake/Modules/CMakeParseArgumentsCopy.cmake @@ -58,7 +58,7 @@ # the new option. # E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in # MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would -# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor. +# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefore. #============================================================================= # Copyright 2010 Alexander Neundorf diff --git a/cmake/Modules/FindGnuradioRuntime.cmake b/cmake/Modules/FindGnuradioRuntime.cmake deleted file mode 100644 index afed684..0000000 --- a/cmake/Modules/FindGnuradioRuntime.cmake +++ /dev/null @@ -1,36 +0,0 @@ -INCLUDE(FindPkgConfig) -PKG_CHECK_MODULES(PC_GNURADIO_RUNTIME gnuradio-runtime) - -if(PC_GNURADIO_RUNTIME_FOUND) - # look for include files - FIND_PATH( - GNURADIO_RUNTIME_INCLUDE_DIRS - NAMES gnuradio/top_block.h - HINTS $ENV{GNURADIO_RUNTIME_DIR}/include - ${PC_GNURADIO_RUNTIME_INCLUDE_DIRS} - ${CMAKE_INSTALL_PREFIX}/include - PATHS /usr/local/include - /usr/include - ) - - # look for libs - FIND_LIBRARY( - GNURADIO_RUNTIME_LIBRARIES - NAMES gnuradio-runtime - HINTS $ENV{GNURADIO_RUNTIME_DIR}/lib - ${PC_GNURADIO_RUNTIME_LIBDIR} - ${CMAKE_INSTALL_PREFIX}/lib/ - ${CMAKE_INSTALL_PREFIX}/lib64/ - PATHS /usr/local/lib - /usr/local/lib64 - /usr/lib - /usr/lib64 - ) - - set(GNURADIO_RUNTIME_FOUND ${PC_GNURADIO_RUNTIME_FOUND}) -endif(PC_GNURADIO_RUNTIME_FOUND) - -INCLUDE(FindPackageHandleStandardArgs) -# do not check GNURADIO_RUNTIME_INCLUDE_DIRS, is not set when default include path us used. -FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_RUNTIME DEFAULT_MSG GNURADIO_RUNTIME_LIBRARIES) -MARK_AS_ADVANCED(GNURADIO_RUNTIME_LIBRARIES GNURADIO_RUNTIME_INCLUDE_DIRS) diff --git a/cmake/Modules/FindPyQt.py b/cmake/Modules/FindPyQt.py deleted file mode 100644 index 5d2f951..0000000 --- a/cmake/Modules/FindPyQt.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2007, Simon Edwards -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - -import PyQt4.pyqtconfig - -pyqtcfg = PyQt4.pyqtconfig.Configuration() -print("pyqt_version:%06.0x" % pyqtcfg.pyqt_version) -print("pyqt_version_str:%s" % pyqtcfg.pyqt_version_str) - -pyqt_version_tag = "" -in_t = False -for item in pyqtcfg.pyqt_sip_flags.split(' '): - if item=="-t": - in_t = True - elif in_t: - if item.startswith("Qt_4"): - pyqt_version_tag = item - else: - in_t = False -print("pyqt_version_tag:%s" % pyqt_version_tag) - -print("pyqt_sip_dir:%s" % pyqtcfg.pyqt_sip_dir) -print("pyqt_sip_flags:%s" % pyqtcfg.pyqt_sip_flags) diff --git a/cmake/Modules/FindPyQt4.cmake b/cmake/Modules/FindPyQt4.cmake deleted file mode 100644 index c1f3f28..0000000 --- a/cmake/Modules/FindPyQt4.cmake +++ /dev/null @@ -1,61 +0,0 @@ -# Find PyQt4 -# ~~~~~~~~~~ -# Copyright (c) 2007-2008, Simon Edwards -# Copyright (c) 2012, Nicholas Corgan -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. -# -# PyQt4 website: http://www.riverbankcomputing.co.uk/pyqt/index.php -# -# Find the installed version of PyQt4. FindPyQt4 should only be called after -# Python has been found. -# -# This file defines the following variables: -# -# PYQT4_VERSION - The version of PyQt4 found expressed as a 6 digit hex number -# suitable for comparision as a string -# -# PYQT4_VERSION_STR - The version of PyQt4 as a human readable string. -# -# PYQT4_VERSION_TAG - The PyQt version tag using by PyQt's sip files. -# -# PYQT4_SIP_DIR - The directory holding the PyQt4 .sip files. -# -# PYQT4_SIP_FLAGS - The SIP flags used to build PyQt. - -IF(EXISTS PYQT4_VERSION AND EXISTS PYUIC4_EXECUTABLE) - # Already in cache, be silent - SET(PYQT4_FOUND TRUE) - SET(PYUIC4_FOUND TRUE) -ELSE(EXISTS PYQT4_VERSION AND EXISTS PYUIC4_EXECUTABLE) - - FIND_FILE(_find_pyqt_py FindPyQt.py PATHS ${CMAKE_MODULE_PATH}) - - EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_pyqt_py} OUTPUT_VARIABLE pyqt_config) - IF(pyqt_config) - STRING(REGEX REPLACE "^pyqt_version:([^\n]+).*$" "\\1" PYQT4_VERSION ${pyqt_config}) - STRING(REGEX REPLACE ".*\npyqt_version_str:([^\n]+).*$" "\\1" PYQT4_VERSION_STR ${pyqt_config}) - STRING(REGEX REPLACE ".*\npyqt_version_tag:([^\n]+).*$" "\\1" PYQT4_VERSION_TAG ${pyqt_config}) - STRING(REGEX REPLACE ".*\npyqt_sip_dir:([^\n]+).*$" "\\1" PYQT4_SIP_DIR ${pyqt_config}) - STRING(REGEX REPLACE ".*\npyqt_sip_flags:([^\n]+).*$" "\\1" PYQT4_SIP_FLAGS ${pyqt_config}) - - SET(PYQT4_FOUND TRUE) - ENDIF(pyqt_config) - - FIND_PROGRAM(PYUIC4_EXECUTABLE NAMES pyuic4) - IF(PYUIC4_EXECUTABLE) - SET(PYUIC4_FOUND TRUE) - ENDIF(PYUIC4_EXECUTABLE) - - IF(PYQT4_FOUND AND PYUIC4_FOUND) - IF(NOT PYQT4_FIND_QUIETLY) - MESSAGE(STATUS "Found PyQt4 version: ${PYQT4_VERSION_STR}") - MESSAGE(STATUS "Found pyuic4: ${PYUIC4_EXECUTABLE}") - ENDIF(NOT PYQT4_FIND_QUIETLY) - ELSE(PYQT4_FOUND AND PYUIC4_FOUND) - IF(PYQT4_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find Python") - ENDIF(PYQT4_FIND_REQUIRED) - ENDIF(PYQT4_FOUND AND PYUIC4_FOUND) - -ENDIF(EXISTS PYQT4_VERSION AND EXISTS PYUIC4_EXECUTABLE) diff --git a/cmake/Modules/FindQwt.cmake b/cmake/Modules/FindQwt.cmake deleted file mode 100644 index 0933f32..0000000 --- a/cmake/Modules/FindQwt.cmake +++ /dev/null @@ -1,41 +0,0 @@ -# - try to find Qwt libraries and include files -# QWT_INCLUDE_DIR where to find qwt_plot.h, etc. -# QWT_LIBRARIES libraries to link against -# QWT_FOUND If false, do not try to use Qwt - -find_path (QWT_INCLUDE_DIRS - NAMES qwt_plot.h - HINTS - ${CMAKE_INSTALL_PREFIX}/include/qwt - ${CMAKE_PREFIX_PATH}/include/qwt - PATHS - /usr/local/include/qwt-qt4 - /usr/local/include/qwt - /usr/include/qwt6 - /usr/include/qwt-qt4 - /usr/include/qwt - /usr/include/qwt5 - /opt/local/include/qwt - /sw/include/qwt - /usr/local/lib/qwt.framework/Headers -) - -find_library (QWT_LIBRARIES - NAMES qwt6 qwt6-qt4 qwt qwt-qt4 qwt5 qwtd5 - HINTS - ${CMAKE_INSTALL_PREFIX}/lib - ${CMAKE_INSTALL_PREFIX}/lib64 - ${CMAKE_PREFIX_PATH}/lib - PATHS - /usr/local/lib - /usr/lib - /opt/local/lib - /sw/lib - /usr/local/lib/qwt.framework -) - -# handle the QUIETLY and REQUIRED arguments and set QWT_FOUND to TRUE if -# all listed variables are TRUE -include ( FindPackageHandleStandardArgs ) -find_package_handle_standard_args( Qwt DEFAULT_MSG QWT_LIBRARIES QWT_INCLUDE_DIRS ) -MARK_AS_ADVANCED(QWT_LIBRARIES QWT_INCLUDE_DIRS) diff --git a/cmake/Modules/GrBoost.cmake b/cmake/Modules/GrBoost.cmake deleted file mode 100644 index fcac5cf..0000000 --- a/cmake/Modules/GrBoost.cmake +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -if(DEFINED __INCLUDED_GR_BOOST_CMAKE) - return() -endif() -set(__INCLUDED_GR_BOOST_CMAKE TRUE) - -######################################################################## -# Setup Boost and handle some system specific things -######################################################################## - -set(BOOST_REQUIRED_COMPONENTS - date_time - program_options - filesystem - system - thread -) - -if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64") - list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix -endif(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64") - -if(MSVC) - set(BOOST_REQUIRED_COMPONENTS ${BOOST_REQUIRED_COMPONENTS} chrono) - - if (NOT DEFINED BOOST_ALL_DYN_LINK) - set(BOOST_ALL_DYN_LINK TRUE) - endif() - set(BOOST_ALL_DYN_LINK "${BOOST_ALL_DYN_LINK}" CACHE BOOL "boost enable dynamic linking") - if(BOOST_ALL_DYN_LINK) - add_definitions(-DBOOST_ALL_DYN_LINK) #setup boost auto-linking in msvc - else(BOOST_ALL_DYN_LINK) - unset(BOOST_REQUIRED_COMPONENTS) #empty components list for static link - endif(BOOST_ALL_DYN_LINK) -endif(MSVC) - -find_package(Boost "1.35" COMPONENTS ${BOOST_REQUIRED_COMPONENTS}) - -# This does not allow us to disable specific versions. It is used -# internally by cmake to know the formation newer versions. As newer -# Boost version beyond what is shown here are produced, we must extend -# this list. To disable Boost versions, see below. -set(Boost_ADDITIONAL_VERSIONS - "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39" - "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44" - "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49" - "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" - "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59" - "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64" - "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" -) - -# Boost 1.52 disabled, see https://svn.boost.org/trac/boost/ticket/7669 -# Similar problems with Boost 1.46 and 1.47. - -OPTION(ENABLE_BAD_BOOST "Enable known bad versions of Boost" OFF) -if(ENABLE_BAD_BOOST) - MESSAGE(STATUS "Enabling use of known bad versions of Boost.") -endif(ENABLE_BAD_BOOST) - -# For any unsuitable Boost version, add the version number below in -# the following format: XXYYZZ -# Where: -# XX is the major version ('10' for version 1) -# YY is the minor version number ('46' for 1.46) -# ZZ is the patcher version number (typically just '00') -set(Boost_NOGO_VERSIONS - 104600 104601 104700 105200 - ) - -foreach(ver ${Boost_NOGO_VERSIONS}) - if("${Boost_VERSION}" STREQUAL "${ver}") - if(NOT ENABLE_BAD_BOOST) - MESSAGE(STATUS "WARNING: Found a known bad version of Boost (v${Boost_VERSION}). Disabling.") - set(Boost_FOUND FALSE) - else(NOT ENABLE_BAD_BOOST) - MESSAGE(STATUS "WARNING: Found a known bad version of Boost (v${Boost_VERSION}). Continuing anyway.") - set(Boost_FOUND TRUE) - endif(NOT ENABLE_BAD_BOOST) - endif("${Boost_VERSION}" STREQUAL "${ver}") -endforeach(ver) diff --git a/cmake/Modules/GrMiscUtils.cmake b/cmake/Modules/GrMiscUtils.cmake deleted file mode 100644 index a73e3e6..0000000 --- a/cmake/Modules/GrMiscUtils.cmake +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -if(DEFINED __INCLUDED_GR_MISC_UTILS_CMAKE) - return() -endif() -set(__INCLUDED_GR_MISC_UTILS_CMAKE TRUE) - -######################################################################## -# Set global variable macro. -# Used for subdirectories to export settings. -# Example: include and library paths. -######################################################################## -function(GR_SET_GLOBAL var) - set(${var} ${ARGN} CACHE INTERNAL "" FORCE) -endfunction(GR_SET_GLOBAL) - -######################################################################## -# Set the pre-processor definition if the condition is true. -# - def the pre-processor definition to set and condition name -######################################################################## -function(GR_ADD_COND_DEF def) - if(${def}) - add_definitions(-D${def}) - endif(${def}) -endfunction(GR_ADD_COND_DEF) - -######################################################################## -# Check for a header and conditionally set a compile define. -# - hdr the relative path to the header file -# - def the pre-processor definition to set -######################################################################## -function(GR_CHECK_HDR_N_DEF hdr def) - include(CheckIncludeFileCXX) - CHECK_INCLUDE_FILE_CXX(${hdr} ${def}) - GR_ADD_COND_DEF(${def}) -endfunction(GR_CHECK_HDR_N_DEF) - -######################################################################## -# Include subdirectory macro. -# Sets the CMake directory variables, -# includes the subdirectory CMakeLists.txt, -# resets the CMake directory variables. -# -# This macro includes subdirectories rather than adding them -# so that the subdirectory can affect variables in the level above. -# This provides a work-around for the lack of convenience libraries. -# This way a subdirectory can append to the list of library sources. -######################################################################## -macro(GR_INCLUDE_SUBDIRECTORY subdir) - #insert the current directories on the front of the list - list(INSERT _cmake_source_dirs 0 ${CMAKE_CURRENT_SOURCE_DIR}) - list(INSERT _cmake_binary_dirs 0 ${CMAKE_CURRENT_BINARY_DIR}) - - #set the current directories to the names of the subdirs - set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}) - set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${subdir}) - - #include the subdirectory CMakeLists to run it - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - include(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt) - - #reset the value of the current directories - list(GET _cmake_source_dirs 0 CMAKE_CURRENT_SOURCE_DIR) - list(GET _cmake_binary_dirs 0 CMAKE_CURRENT_BINARY_DIR) - - #pop the subdir names of the front of the list - list(REMOVE_AT _cmake_source_dirs 0) - list(REMOVE_AT _cmake_binary_dirs 0) -endmacro(GR_INCLUDE_SUBDIRECTORY) - -######################################################################## -# Check if a compiler flag works and conditionally set a compile define. -# - flag the compiler flag to check for -# - have the variable to set with result -######################################################################## -macro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE flag have) - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG(${flag} ${have}) - if(${have}) - add_definitions(${flag}) - endif(${have}) -endmacro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE) - -######################################################################## -# Generates the .la libtool file -# This appears to generate libtool files that cannot be used by auto*. -# Usage GR_LIBTOOL(TARGET [target] DESTINATION [dest]) -# Notice: there is not COMPONENT option, these will not get distributed. -######################################################################## -function(GR_LIBTOOL) - if(NOT DEFINED GENERATE_LIBTOOL) - set(GENERATE_LIBTOOL OFF) #disabled by default - endif() - - if(GENERATE_LIBTOOL) - include(CMakeParseArgumentsCopy) - CMAKE_PARSE_ARGUMENTS(GR_LIBTOOL "" "TARGET;DESTINATION" "" ${ARGN}) - - find_program(LIBTOOL libtool) - if(LIBTOOL) - include(CMakeMacroLibtoolFile) - CREATE_LIBTOOL_FILE(${GR_LIBTOOL_TARGET} /${GR_LIBTOOL_DESTINATION}) - endif(LIBTOOL) - endif(GENERATE_LIBTOOL) - -endfunction(GR_LIBTOOL) - -######################################################################## -# Do standard things to the library target -# - set target properties -# - make install rules -# Also handle gnuradio custom naming conventions w/ extras mode. -######################################################################## -function(GR_LIBRARY_FOO target) - #parse the arguments for component names - include(CMakeParseArgumentsCopy) - CMAKE_PARSE_ARGUMENTS(GR_LIBRARY "" "RUNTIME_COMPONENT;DEVEL_COMPONENT" "" ${ARGN}) - - #set additional target properties - set_target_properties(${target} PROPERTIES SOVERSION ${LIBVER}) - - #install the generated files like so... - install(TARGETS ${target} - LIBRARY DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .so/.dylib file - ARCHIVE DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_DEVEL_COMPONENT} # .lib file - RUNTIME DESTINATION ${GR_RUNTIME_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .dll file - ) - - #extras mode enabled automatically on linux - if(NOT DEFINED LIBRARY_EXTRAS) - set(LIBRARY_EXTRAS ${LINUX}) - endif() - - #special extras mode to enable alternative naming conventions - if(LIBRARY_EXTRAS) - - #create .la file before changing props - GR_LIBTOOL(TARGET ${target} DESTINATION ${GR_LIBRARY_DIR}) - - #give the library a special name with ultra-zero soversion - set_target_properties(${target} PROPERTIES OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0") - set(target_name lib${target}-${LIBVER}.so.0.0.0) - - #custom command to generate symlinks - add_custom_command( - TARGET ${target} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so - COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0 - COMMAND ${CMAKE_COMMAND} -E touch ${target_name} #so the symlinks point to something valid so cmake 2.6 will install - ) - - #and install the extra symlinks - install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so - ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0 - DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} - ) - - endif(LIBRARY_EXTRAS) -endfunction(GR_LIBRARY_FOO) - -######################################################################## -# Create a dummy custom command that depends on other targets. -# Usage: -# GR_GEN_TARGET_DEPS(unique_name target_deps ...) -# ADD_CUSTOM_COMMAND( ${target_deps}) -# -# Custom command cant depend on targets, but can depend on executables, -# and executables can depend on targets. So this is the process: -######################################################################## -function(GR_GEN_TARGET_DEPS name var) - file( - WRITE ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in - "int main(void){return 0;}\n" - ) - execute_process( - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in - ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp - ) - add_executable(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp) - if(ARGN) - add_dependencies(${name} ${ARGN}) - endif(ARGN) - - if(CMAKE_CROSSCOMPILING) - set(${var} "DEPENDS;${name}" PARENT_SCOPE) #cant call command when cross - else() - set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE) - endif() -endfunction(GR_GEN_TARGET_DEPS) diff --git a/cmake/Modules/GrPlatform.cmake b/cmake/Modules/GrPlatform.cmake deleted file mode 100644 index 5b7e886..0000000 --- a/cmake/Modules/GrPlatform.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -if(DEFINED __INCLUDED_GR_PLATFORM_CMAKE) - return() -endif() -set(__INCLUDED_GR_PLATFORM_CMAKE TRUE) - -######################################################################## -# Setup additional defines for OS types -######################################################################## -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(LINUX TRUE) -endif() - -if(LINUX AND EXISTS "/etc/debian_version") - set(DEBIAN TRUE) -endif() - -if(LINUX AND EXISTS "/etc/redhat-release") - set(REDHAT TRUE) -endif() - -if(LINUX AND EXISTS "/etc/slackware-version") - set(SLACKWARE TRUE) -endif() - -######################################################################## -# when the library suffix should be 64 (applies to redhat linux family) -######################################################################## -if (REDHAT OR SLACKWARE) - set(LIB64_CONVENTION TRUE) -endif() - -if(NOT DEFINED LIB_SUFFIX AND LIB64_CONVENTION AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$") - set(LIB_SUFFIX 64) -endif() -set(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix") diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake deleted file mode 100644 index 14f2b29..0000000 --- a/cmake/Modules/GrPython.cmake +++ /dev/null @@ -1,232 +0,0 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -if(DEFINED __INCLUDED_GR_PYTHON_CMAKE) - return() -endif() -set(__INCLUDED_GR_PYTHON_CMAKE TRUE) - -######################################################################## -# Setup the python interpreter: -# This allows the user to specify a specific interpreter, -# or finds the interpreter via the built-in cmake module. -######################################################################## -#this allows the user to override PYTHON_EXECUTABLE -if(PYTHON_EXECUTABLE) - - set(PYTHONINTERP_FOUND TRUE) - -#otherwise if not set, try to automatically find it -else(PYTHON_EXECUTABLE) - - #use the built-in find script - find_package(PythonInterp) - - #and if that fails use the find program routine - if(NOT PYTHONINTERP_FOUND) - find_program(PYTHON_EXECUTABLE NAMES python python2.7 python2.6 python2.5) - if(PYTHON_EXECUTABLE) - set(PYTHONINTERP_FOUND TRUE) - endif(PYTHON_EXECUTABLE) - endif(NOT PYTHONINTERP_FOUND) - -endif(PYTHON_EXECUTABLE) - -#make the path to the executable appear in the cmake gui -set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter") - -#make sure we can use -B with python (introduced in 2.6) -if(PYTHON_EXECUTABLE) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -B -c "" - OUTPUT_QUIET ERROR_QUIET - RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT - ) - if(PYTHON_HAS_DASH_B_RESULT EQUAL 0) - set(PYTHON_DASH_B "-B") - endif() -endif(PYTHON_EXECUTABLE) - -######################################################################## -# Check for the existence of a python module: -# - desc a string description of the check -# - mod the name of the module to import -# - cmd an additional command to run -# - have the result variable to set -######################################################################## -macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) - message(STATUS "") - message(STATUS "Python checking for ${desc}") - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c " -######################################### -try: - import ${mod} - assert ${cmd} -except ImportError, AssertionError: exit(-1) -except: pass -#########################################" - RESULT_VARIABLE ${have} - ) - if(${have} EQUAL 0) - message(STATUS "Python checking for ${desc} - found") - set(${have} TRUE) - else(${have} EQUAL 0) - message(STATUS "Python checking for ${desc} - not found") - set(${have} FALSE) - endif(${have} EQUAL 0) -endmacro(GR_PYTHON_CHECK_MODULE) - -######################################################################## -# Sets the python installation directory GR_PYTHON_DIR -######################################################################## -execute_process(COMMAND ${PYTHON_EXECUTABLE} -c " -from distutils import sysconfig -print sysconfig.get_python_lib(plat_specific=True, prefix='') -" OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE -) -file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR) - -######################################################################## -# Create an always-built target with a unique name -# Usage: GR_UNIQUE_TARGET( ) -######################################################################## -function(GR_UNIQUE_TARGET desc) - file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib -unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5] -print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))" - OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE) - add_custom_target(${_target} ALL DEPENDS ${ARGN}) -endfunction(GR_UNIQUE_TARGET) - -######################################################################## -# Install python sources (also builds and installs byte-compiled python) -######################################################################## -function(GR_PYTHON_INSTALL) - include(CMakeParseArgumentsCopy) - CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN}) - - #################################################################### - if(GR_PYTHON_INSTALL_FILES) - #################################################################### - install(${ARGN}) #installs regular python files - - #create a list of all generated files - unset(pysrcfiles) - unset(pycfiles) - unset(pyofiles) - foreach(pyfile ${GR_PYTHON_INSTALL_FILES}) - get_filename_component(pyfile ${pyfile} ABSOLUTE) - list(APPEND pysrcfiles ${pyfile}) - - #determine if this file is in the source or binary directory - file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile}) - string(LENGTH "${source_rel_path}" source_rel_path_len) - file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile}) - string(LENGTH "${binary_rel_path}" binary_rel_path_len) - - #and set the generated path appropriately - if(${source_rel_path_len} GREATER ${binary_rel_path_len}) - set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path}) - else() - set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path}) - endif() - list(APPEND pycfiles ${pygenfile}c) - list(APPEND pyofiles ${pygenfile}o) - - #ensure generation path exists - get_filename_component(pygen_path ${pygenfile} PATH) - file(MAKE_DIRECTORY ${pygen_path}) - - endforeach(pyfile) - - #the command to generate the pyc files - add_custom_command( - DEPENDS ${pysrcfiles} OUTPUT ${pycfiles} - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles} - ) - - #the command to generate the pyo files - add_custom_command( - DEPENDS ${pysrcfiles} OUTPUT ${pyofiles} - COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles} - ) - - #create install rule and add generated files to target list - set(python_install_gen_targets ${pycfiles} ${pyofiles}) - install(FILES ${python_install_gen_targets} - DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} - COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} - ) - - - #################################################################### - elseif(GR_PYTHON_INSTALL_PROGRAMS) - #################################################################### - file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native) - - if (CMAKE_CROSSCOMPILING) - set(pyexe_native /usr/bin/env python) - endif() - - foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS}) - get_filename_component(pyfile_name ${pyfile} NAME) - get_filename_component(pyfile ${pyfile} ABSOLUTE) - string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe") - list(APPEND python_install_gen_targets ${pyexefile}) - - get_filename_component(pyexefile_path ${pyexefile} PATH) - file(MAKE_DIRECTORY ${pyexefile_path}) - - add_custom_command( - OUTPUT ${pyexefile} DEPENDS ${pyfile} - COMMAND ${PYTHON_EXECUTABLE} -c - \"open('${pyexefile}', 'w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())\" - COMMENT "Shebangin ${pyfile_name}" - ) - - #on windows, python files need an extension to execute - get_filename_component(pyfile_ext ${pyfile} EXT) - if(WIN32 AND NOT pyfile_ext) - set(pyfile_name "${pyfile_name}.py") - endif() - - install(PROGRAMS ${pyexefile} RENAME ${pyfile_name} - DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} - COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} - ) - endforeach(pyfile) - - endif() - - GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets}) - -endfunction(GR_PYTHON_INSTALL) - -######################################################################## -# Write the python helper script that generates byte code files -######################################################################## -file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py " -import sys, py_compile -files = sys.argv[1:] -srcs, gens = files[:len(files)/2], files[len(files)/2:] -for src, gen in zip(srcs, gens): - py_compile.compile(file=src, cfile=gen, doraise=True) -") diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake deleted file mode 100644 index 175d0d7..0000000 --- a/cmake/Modules/GrSwig.cmake +++ /dev/null @@ -1,232 +0,0 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -if(DEFINED __INCLUDED_GR_SWIG_CMAKE) - return() -endif() -set(__INCLUDED_GR_SWIG_CMAKE TRUE) - -include(GrPython) - -######################################################################## -# Builds a swig documentation file to be generated into python docstrings -# Usage: GR_SWIG_MAKE_DOCS(output_file input_path input_path....) -# -# Set the following variable to specify extra dependent targets: -# - GR_SWIG_DOCS_SOURCE_DEPS -# - GR_SWIG_DOCS_TARGET_DEPS -######################################################################## -function(GR_SWIG_MAKE_DOCS output_file) - if(ENABLE_DOXYGEN) - - #setup the input files variable list, quote formated - set(input_files) - unset(INPUT_PATHS) - foreach(input_path ${ARGN}) - if (IS_DIRECTORY ${input_path}) #when input path is a directory - file(GLOB input_path_h_files ${input_path}/*.h) - else() #otherwise its just a file, no glob - set(input_path_h_files ${input_path}) - endif() - list(APPEND input_files ${input_path_h_files}) - set(INPUT_PATHS "${INPUT_PATHS} \"${input_path}\"") - endforeach(input_path) - - #determine the output directory - get_filename_component(name ${output_file} NAME_WE) - get_filename_component(OUTPUT_DIRECTORY ${output_file} PATH) - set(OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}/${name}_swig_docs) - make_directory(${OUTPUT_DIRECTORY}) - - #generate the Doxyfile used by doxygen - configure_file( - ${CMAKE_SOURCE_DIR}/docs/doxygen/Doxyfile.swig_doc.in - ${OUTPUT_DIRECTORY}/Doxyfile - @ONLY) - - #Create a dummy custom command that depends on other targets - include(GrMiscUtils) - GR_GEN_TARGET_DEPS(_${name}_tag tag_deps ${GR_SWIG_DOCS_TARGET_DEPS}) - - #call doxygen on the Doxyfile + input headers - add_custom_command( - OUTPUT ${OUTPUT_DIRECTORY}/xml/index.xml - DEPENDS ${input_files} ${GR_SWIG_DOCS_SOURCE_DEPS} ${tag_deps} - COMMAND ${DOXYGEN_EXECUTABLE} ${OUTPUT_DIRECTORY}/Doxyfile - COMMENT "Generating doxygen xml for ${name} docs" - ) - - #call the swig_doc script on the xml files - add_custom_command( - OUTPUT ${output_file} - DEPENDS ${input_files} ${stamp-file} ${OUTPUT_DIRECTORY}/xml/index.xml - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} - ${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py - ${OUTPUT_DIRECTORY}/xml - ${output_file} - COMMENT "Generating python docstrings for ${name}" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs/doxygen - ) - - else(ENABLE_DOXYGEN) - file(WRITE ${output_file} "\n") #no doxygen -> empty file - endif(ENABLE_DOXYGEN) -endfunction(GR_SWIG_MAKE_DOCS) - -######################################################################## -# Build a swig target for the common gnuradio use case. Usage: -# GR_SWIG_MAKE(target ifile ifile ifile...) -# -# Set the following variables before calling: -# - GR_SWIG_FLAGS -# - GR_SWIG_INCLUDE_DIRS -# - GR_SWIG_LIBRARIES -# - GR_SWIG_SOURCE_DEPS -# - GR_SWIG_TARGET_DEPS -# - GR_SWIG_DOC_FILE -# - GR_SWIG_DOC_DIRS -######################################################################## -macro(GR_SWIG_MAKE name) - set(ifiles ${ARGN}) - - list(APPEND GR_SWIG_TARGET_DEPS ${GR_SWIG_LIBRARIES}) - - #do swig doc generation if specified - if (GR_SWIG_DOC_FILE) - set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS}) - set(GR_SWIG_DOCS_TAREGT_DEPS ${GR_SWIG_TARGET_DEPS}) - GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS}) - add_custom_target(${name}_swig_doc DEPENDS ${GR_SWIG_DOC_FILE}) - list(APPEND GR_SWIG_TARGET_DEPS ${name}_swig_doc) - endif() - - #append additional include directories - find_package(PythonLibs) - list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs) - list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) - list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) - list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) - - #determine include dependencies for swig file - execute_process( - COMMAND ${PYTHON_EXECUTABLE} - ${CMAKE_BINARY_DIR}/get_swig_deps.py - "${ifiles}" "${GR_SWIG_INCLUDE_DIRS}" - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE SWIG_MODULE_${name}_EXTRA_DEPS - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - - #Create a dummy custom command that depends on other targets - include(GrMiscUtils) - GR_GEN_TARGET_DEPS(_${name}_swig_tag tag_deps ${GR_SWIG_TARGET_DEPS}) - set(tag_file ${CMAKE_CURRENT_BINARY_DIR}/${name}.tag) - add_custom_command( - OUTPUT ${tag_file} - DEPENDS ${GR_SWIG_SOURCE_DEPS} ${tag_deps} - COMMAND ${CMAKE_COMMAND} -E touch ${tag_file} - ) - - #append the specified include directories - include_directories(${GR_SWIG_INCLUDE_DIRS}) - list(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${tag_file}) - - #setup the swig flags with flags and include directories - set(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -module ${name} ${GR_SWIG_FLAGS}) - foreach(dir ${GR_SWIG_INCLUDE_DIRS}) - list(APPEND CMAKE_SWIG_FLAGS "-I${dir}") - endforeach(dir) - - #set the C++ property on the swig .i file so it builds - set_source_files_properties(${ifiles} PROPERTIES CPLUSPLUS ON) - - #setup the actual swig library target to be built - include(UseSWIG) - SWIG_ADD_MODULE(${name} python ${ifiles}) - SWIG_LINK_LIBRARIES(${name} ${PYTHON_LIBRARIES} ${GR_SWIG_LIBRARIES}) - -endmacro(GR_SWIG_MAKE) - -######################################################################## -# Install swig targets generated by GR_SWIG_MAKE. Usage: -# GR_SWIG_INSTALL( -# TARGETS target target target... -# [DESTINATION destination] -# [COMPONENT component] -# ) -######################################################################## -macro(GR_SWIG_INSTALL) - - include(CMakeParseArgumentsCopy) - CMAKE_PARSE_ARGUMENTS(GR_SWIG_INSTALL "" "DESTINATION;COMPONENT" "TARGETS" ${ARGN}) - - foreach(name ${GR_SWIG_INSTALL_TARGETS}) - install(TARGETS ${SWIG_MODULE_${name}_REAL_NAME} - DESTINATION ${GR_SWIG_INSTALL_DESTINATION} - COMPONENT ${GR_SWIG_INSTALL_COMPONENT} - ) - - include(GrPython) - GR_PYTHON_INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}.py - DESTINATION ${GR_SWIG_INSTALL_DESTINATION} - COMPONENT ${GR_SWIG_INSTALL_COMPONENT} - ) - - GR_LIBTOOL( - TARGET ${SWIG_MODULE_${name}_REAL_NAME} - DESTINATION ${GR_SWIG_INSTALL_DESTINATION} - ) - - endforeach(name) - -endmacro(GR_SWIG_INSTALL) - -######################################################################## -# Generate a python file that can determine swig dependencies. -# Used by the make macro above to determine extra dependencies. -# When you build C++, CMake figures out the header dependencies. -# This code essentially performs that logic for swig includes. -######################################################################## -file(WRITE ${CMAKE_BINARY_DIR}/get_swig_deps.py " - -import os, sys, re - -include_matcher = re.compile('[#|%]include\\s*[<|\"](.*)[>|\"]') -include_dirs = sys.argv[2].split(';') - -def get_swig_incs(file_path): - file_contents = open(file_path, 'r').read() - return include_matcher.findall(file_contents, re.MULTILINE) - -def get_swig_deps(file_path, level): - deps = [file_path] - if level == 0: return deps - for inc_file in get_swig_incs(file_path): - for inc_dir in include_dirs: - inc_path = os.path.join(inc_dir, inc_file) - if not os.path.exists(inc_path): continue - deps.extend(get_swig_deps(inc_path, level-1)) - return deps - -if __name__ == '__main__': - ifiles = sys.argv[1].split(';') - deps = sum([get_swig_deps(ifile, 3) for ifile in ifiles], []) - #sys.stderr.write(';'.join(set(deps)) + '\\n\\n') - print(';'.join(set(deps))) -") diff --git a/cmake/Modules/GrTest.cmake b/cmake/Modules/GrTest.cmake deleted file mode 100644 index 4723cca..0000000 --- a/cmake/Modules/GrTest.cmake +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -if(DEFINED __INCLUDED_GR_TEST_CMAKE) - return() -endif() -set(__INCLUDED_GR_TEST_CMAKE TRUE) - -######################################################################## -# Add a unit test and setup the environment for a unit test. -# Takes the same arguments as the ADD_TEST function. -# -# Before calling set the following variables: -# GR_TEST_TARGET_DEPS - built targets for the library path -# GR_TEST_LIBRARY_DIRS - directories for the library path -# GR_TEST_PYTHON_DIRS - directories for the python path -######################################################################## -function(GR_ADD_TEST test_name) - - #Ensure that the build exe also appears in the PATH. - list(APPEND GR_TEST_TARGET_DEPS ${ARGN}) - - #In the land of windows, all libraries must be in the PATH. - #Since the dependent libraries are not yet installed, - #we must manually set them in the PATH to run tests. - #The following appends the path of a target dependency. - foreach(target ${GR_TEST_TARGET_DEPS}) - get_target_property(location ${target} LOCATION) - if(location) - get_filename_component(path ${location} PATH) - string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} path ${path}) - list(APPEND GR_TEST_LIBRARY_DIRS ${path}) - endif(location) - endforeach(target) - - if(WIN32) - #SWIG generates the python library files into a subdirectory. - #Therefore, we must append this subdirectory into PYTHONPATH. - #Only do this for the python directories matching the following: - foreach(pydir ${GR_TEST_PYTHON_DIRS}) - get_filename_component(name ${pydir} NAME) - if(name MATCHES "^(swig|lib|src)$") - list(APPEND GR_TEST_PYTHON_DIRS ${pydir}/${CMAKE_BUILD_TYPE}) - endif() - endforeach(pydir) - endif(WIN32) - - file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} srcdir) - file(TO_NATIVE_PATH "${GR_TEST_LIBRARY_DIRS}" libpath) #ok to use on dir list? - file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list? - - set(environs "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}") - - #http://www.cmake.org/pipermail/cmake/2009-May/029464.html - #Replaced this add test + set environs code with the shell script generation. - #Its nicer to be able to manually run the shell script to diagnose problems. - #ADD_TEST(${ARGV}) - #SET_TESTS_PROPERTIES(${test_name} PROPERTIES ENVIRONMENT "${environs}") - - if(UNIX) - set(LD_PATH_VAR "LD_LIBRARY_PATH") - if(APPLE) - set(LD_PATH_VAR "DYLD_LIBRARY_PATH") - endif() - - set(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH") - list(APPEND libpath "$${LD_PATH_VAR}") - list(APPEND pypath "$PYTHONPATH") - - #replace list separator with the path separator - string(REPLACE ";" ":" libpath "${libpath}") - string(REPLACE ";" ":" pypath "${pypath}") - list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}") - - #generate a bat file that sets the environment and runs the test - find_program(SHELL sh) - set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh) - file(WRITE ${sh_file} "#!${SHELL}\n") - #each line sets an environment variable - foreach(environ ${environs}) - file(APPEND ${sh_file} "export ${environ}\n") - endforeach(environ) - #load the command to run with its arguments - foreach(arg ${ARGN}) - file(APPEND ${sh_file} "${arg} ") - endforeach(arg) - file(APPEND ${sh_file} "\n") - - #make the shell file executable - execute_process(COMMAND chmod +x ${sh_file}) - - add_test(${test_name} ${SHELL} ${sh_file}) - - endif(UNIX) - - if(WIN32) - list(APPEND libpath ${DLL_PATHS} "%PATH%") - list(APPEND pypath "%PYTHONPATH%") - - #replace list separator with the path separator (escaped) - string(REPLACE ";" "\\;" libpath "${libpath}") - string(REPLACE ";" "\\;" pypath "${pypath}") - list(APPEND environs "PATH=${libpath}" "PYTHONPATH=${pypath}") - - #generate a bat file that sets the environment and runs the test - set(bat_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.bat) - file(WRITE ${bat_file} "@echo off\n") - #each line sets an environment variable - foreach(environ ${environs}) - file(APPEND ${bat_file} "SET ${environ}\n") - endforeach(environ) - #load the command to run with its arguments - foreach(arg ${ARGN}) - file(APPEND ${bat_file} "${arg} ") - endforeach(arg) - file(APPEND ${bat_file} "\n") - - add_test(${test_name} ${bat_file}) - endif(WIN32) - -endfunction(GR_ADD_TEST) diff --git a/cmake/Modules/air_modesConfig.cmake b/cmake/Modules/air_modesConfig.cmake new file mode 100644 index 0000000..9e787cb --- /dev/null +++ b/cmake/Modules/air_modesConfig.cmake @@ -0,0 +1,31 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_AIR_MODES air_modes) + +FIND_PATH( + AIR_MODES_INCLUDE_DIRS + NAMES air_modes/api.h + HINTS $ENV{AIR_MODES_DIR}/include + ${PC_AIR_MODES_INCLUDEDIR} + PATHS ${CMAKE_INSTALL_PREFIX}/include + /usr/local/include + /usr/include +) + +FIND_LIBRARY( + AIR_MODES_LIBRARIES + NAMES gnuradio-air-modes + HINTS $ENV{AIR_MODES_DIR}/lib + ${PC_AIR_MODES_LIBDIR} + PATHS ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 + ) + +include("${CMAKE_CURRENT_LIST_DIR}/air_modesTarget.cmake") + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(AIR_MODES DEFAULT_MSG AIR_MODES_LIBRARIES AIR_MODES_INCLUDE_DIRS) +MARK_AS_ADVANCED(AIR_MODES_LIBRARIES AIR_MODES_INCLUDE_DIRS) diff --git a/cmake/Modules/targetConfig.cmake.in b/cmake/Modules/targetConfig.cmake.in new file mode 100644 index 0000000..79e4a28 --- /dev/null +++ b/cmake/Modules/targetConfig.cmake.in @@ -0,0 +1,26 @@ +# Copyright 2018 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +include(CMakeFindDependencyMacro) + +set(target_deps "@TARGET_DEPENDENCIES@") +foreach(dep IN LISTS target_deps) + find_dependency(${dep}) +endforeach() +include("${CMAKE_CURRENT_LIST_DIR}/@TARGET@Targets.cmake") diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e3bd53a..7e813dc 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -27,34 +27,29 @@ add_library(air_modes SHARED slicer_impl.cc modes_crc.cc ) -target_link_libraries(air_modes ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES}) +target_link_libraries(air_modes gnuradio::gnuradio-runtime) +target_include_directories(air_modes + PUBLIC $ + PUBLIC $ + ) set_target_properties(air_modes PROPERTIES DEFINE_SYMBOL "AIR_MODES_EXPORTS") -set_target_properties(air_modes PROPERTIES SOVERSION "${gr-gr-air-modes_VERSION_MAJOR}") -set_target_properties(air_modes PROPERTIES VERSION "${gr-gr-air-modes_VERSION_MAJOR}.${gr-gr-air-modes_VERSION_MINOR}") +set_target_properties(air_modes PROPERTIES SOVERSION "${VERSION_MAJOR}") +set_target_properties(air_modes PROPERTIES VERSION "${VERSION_MAJOR}.${VERSION_MINOR}") + +if(APPLE) + set_target_properties(air_modes PROPERTIES + INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" + ) +endif(APPLE) ######################################################################## # Install built library files ######################################################################## -install(TARGETS air_modes - LIBRARY DESTINATION lib${LIB_SUFFIX} # .so/.dylib file - ARCHIVE DESTINATION lib${LIB_SUFFIX} # .lib file - RUNTIME DESTINATION bin # .dll file -) +include(GrMiscUtils) +GR_LIBRARY_FOO(air_modes) ######################################################################## -# Build and register unit test +# Print summary ######################################################################## -#find_package(Boost COMPONENTS unit_test_framework) - -#include(GrTest) -#set(GR_TEST_TARGET_DEPS gnuradio-gr-air-modes) -#turn each test cpp file into an executable with an int main() function -#add_definitions(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN) - -#add_executable(qa_gr-air-modes_square_ff qa_gr-air-modes_square_ff.cc) -#target_link_libraries(qa_gr-air-modes_square_ff gnuradio-gr-air-modes ${Boost_LIBRARIES}) -#GR_ADD_TEST(qa_gr-air-modes_square_ff qa_gr-air-modes_square_ff) - -#add_executable(qa_gr-air-modes_square2_ff qa_gr-air-modes_square2_ff.cc) -#target_link_libraries(qa_gr-air-modes_square2_ff gnuradio-gr-air-modes ${Boost_LIBRARIES}) -#GR_ADD_TEST(qa_gr-air-modes_square2_ff qa_gr-air-modes_square2_ff) +message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}") +message(STATUS "Building for version: ${VERSION} / ${LIBVER}") diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index e748bca..fc16854 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -40,6 +40,7 @@ GR_PYTHON_INSTALL( flightgear.py gui_model.py kml.py + modes_types.py parse.py msprint.py radio.py @@ -47,7 +48,6 @@ GR_PYTHON_INSTALL( rx_path.py sbs1.py sql.py - types.py zmq_socket.py Quaternion.py DESTINATION ${GR_PYTHON_DIR}/air_modes diff --git a/python/__init__.py b/python/__init__.py index a123a9e..ea27b57 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -28,26 +28,10 @@ an experimental implementation of a multilateration solver. ''' -# ---------------------------------------------------------------- -# Temporary workaround for ticket:181 (swig+python problem) -import sys -_RTLD_GLOBAL = 0 -try: - from dl import RTLD_GLOBAL as _RTLD_GLOBAL -except ImportError: - try: - from DLFCN import RTLD_GLOBAL as _RTLD_GLOBAL - except ImportError: - pass - -if _RTLD_GLOBAL != 0: - _dlopenflags = sys.getdlopenflags() - sys.setdlopenflags(_dlopenflags|_RTLD_GLOBAL) -# ---------------------------------------------------------------- - +from __future__ import unicode_literals # import swig generated symbols into the gr-air-modes namespace -from air_modes_swig import * +from .air_modes_swig import * # import any pure python here # @@ -57,30 +41,24 @@ except ImportError: raise RuntimeError("PyZMQ not found! Please install libzmq and PyZMQ to run gr-air-modes") -from rx_path import rx_path -from zmq_socket import zmq_pubsub_iface -from parse import * -from msprint import output_print -from sql import output_sql -from sbs1 import output_sbs1 -from kml import output_kml, output_jsonp -from raw_server import raw_server -from radio import modes_radio -from exceptions import * -from types import * -from altitude import * -from cpr import cpr_decoder -from html_template import html_template +from .rx_path import rx_path +from .zmq_socket import zmq_pubsub_iface +from .parse import * +from .msprint import output_print +from .sql import output_sql +from .sbs1 import output_sbs1 +from .kml import output_kml, output_jsonp +from .raw_server import raw_server +from .radio import modes_radio +from .exceptions import * +from .modes_types import * +from .altitude import * +from .cpr import cpr_decoder +from .html_template import html_template #this is try/excepted in case the user doesn't have numpy installed try: - from flightgear import output_flightgear - from Quaternion import * + from .flightgear import output_flightgear + from .Quaternion import * except ImportError: - print "gr-air-modes warning: numpy+scipy not installed, FlightGear interface not supported" + print("gr-air-modes warning: numpy+scipy not installed, FlightGear interface not supported") pass - -# ---------------------------------------------------------------- -# Tail of workaround -if _RTLD_GLOBAL != 0: - sys.setdlopenflags(_dlopenflags) # Restore original flags -# ---------------------------------------------------------------- diff --git a/python/altitude.py b/python/altitude.py index 1824194..e950300 100755 --- a/python/altitude.py +++ b/python/altitude.py @@ -26,120 +26,119 @@ from air_modes.exceptions import * def decode_alt(alt, bit13): - mbit = alt & 0x0040 - qbit = alt & 0x0010 - - if mbit and bit13: - #nobody uses metric altitude: AFAIK, it's an orphaned part of - #the spec. haven't seen it in three years. as a result, replies - #with mbit set can be considered spurious, and so we discard them here. - - #bits 20-25, 27-31 encode alt in meters - #remember that bits are LSB (bit 20 is MSB) - #meters_alt = 0 - #for (shift, bit) in enumerate(range(31,26,-1)+range(25,19,-1)): - # meters_alt += ((alt & (1<> 2 - tmp2 = (alt & 0x0020) >> 1 - else: - tmp1 = (alt & 0x1FE0) >> 1 - tmp2 = 0 - - decoded_alt = ((alt & 0x0F) | tmp1 | tmp2) * 25 - 1000 - - else: #a mode C-style reply - #okay, the order they come in is: - #C1 A1 C2 A2 C4 A4 X B1 D1 B2 D2 B4 D4 - #the order we want them in is: - #D2 D4 A1 A2 A4 B1 B2 B4 - #so we'll reassemble into a Gray-coded representation - - if bit13 is False: - alt = (alt & 0x003F) | (alt & 0x0FC0 << 1) - - C1 = 0x1000 - A1 = 0x0800 - C2 = 0x0400 - A2 = 0x0200 #this represents the order in which the bits come - C4 = 0x0100 - A4 = 0x0080 - B1 = 0x0020 - D1 = 0x0010 - B2 = 0x0008 - D2 = 0x0004 - B4 = 0x0002 - D4 = 0x0001 - - bigpart = ((alt & B4) >> 1) \ - + ((alt & B2) >> 2) \ - + ((alt & B1) >> 3) \ - + ((alt & A4) >> 4) \ - + ((alt & A2) >> 5) \ - + ((alt & A1) >> 6) \ - + ((alt & D4) << 6) \ - + ((alt & D2) << 5) - - #bigpart is now the 500-foot-resolution Gray-coded binary part - decoded_alt = gray2bin(bigpart) - #real_alt is now the 500-foot-per-tick altitude - - cbits = ((alt & C4) >> 8) + ((alt & C2) >> 9) + ((alt & C1) >> 10) - cval = gray2bin(cbits) #turn them into a real number - - if cval == 7: - cval = 5 #not a real gray code after all - - if decoded_alt % 2: - cval = 6 - cval #since the code is symmetric this unwraps it to see whether to subtract the C bits or add them - - decoded_alt *= 500 #take care of the A,B,D data - decoded_alt += cval * 100 #factor in the C data - decoded_alt -= 1300 #subtract the offset - - return decoded_alt + mbit = alt & 0x0040 + qbit = alt & 0x0010 + + if mbit and bit13: + #nobody uses metric altitude: AFAIK, it's an orphaned part of + #the spec. haven't seen it in three years. as a result, replies + #with mbit set can be considered spurious, and so we discard them here. + + #bits 20-25, 27-31 encode alt in meters + #remember that bits are LSB (bit 20 is MSB) + #meters_alt = 0 + #for (shift, bit) in enumerate(range(31,26,-1)+range(25,19,-1)): + # meters_alt += ((alt & (1<> 2 + tmp2 = (alt & 0x0020) >> 1 + else: + tmp1 = (alt & 0x1FE0) >> 1 + tmp2 = 0 + + decoded_alt = ((alt & 0x0F) | tmp1 | tmp2) * 25 - 1000 + + else: #a mode C-style reply + #okay, the order they come in is: + #C1 A1 C2 A2 C4 A4 X B1 D1 B2 D2 B4 D4 + #the order we want them in is: + #D2 D4 A1 A2 A4 B1 B2 B4 + #so we'll reassemble into a Gray-coded representation + + if bit13 is False: + alt = (alt & 0x003F) | (alt & 0x0FC0 << 1) + + C1 = 0x1000 + A1 = 0x0800 + C2 = 0x0400 + A2 = 0x0200 #this represents the order in which the bits come + C4 = 0x0100 + A4 = 0x0080 + B1 = 0x0020 + D1 = 0x0010 + B2 = 0x0008 + D2 = 0x0004 + B4 = 0x0002 + D4 = 0x0001 + + bigpart = ((alt & B4) >> 1) \ + + ((alt & B2) >> 2) \ + + ((alt & B1) >> 3) \ + + ((alt & A4) >> 4) \ + + ((alt & A2) >> 5) \ + + ((alt & A1) >> 6) \ + + ((alt & D4) << 6) \ + + ((alt & D2) << 5) + + #bigpart is now the 500-foot-resolution Gray-coded binary part + decoded_alt = gray2bin(bigpart) + #real_alt is now the 500-foot-per-tick altitude + + cbits = ((alt & C4) >> 8) + ((alt & C2) >> 9) + ((alt & C1) >> 10) + cval = gray2bin(cbits) #turn them into a real number + + if cval == 7: + cval = 5 #not a real gray code after all + + if decoded_alt % 2: + cval = 6 - cval #since the code is symmetric this unwraps it to see whether to subtract the C bits or add them + + decoded_alt *= 500 #take care of the A,B,D data + decoded_alt += cval * 100 #factor in the C data + decoded_alt -= 1300 #subtract the offset + + return decoded_alt def gray2bin(gray): - i = gray >> 1 + i = gray >> 1 - while i != 0: - gray ^= i - i >>= 1 + while i != 0: + gray ^= i + i >>= 1 - return gray + return gray def encode_alt_modes(alt, bit13): - mbit = False - qbit = True - encalt = (int(alt) + 1000) / 25 + mbit = False + qbit = True + encalt = (int(alt) + 1000) / 25 - if bit13 is True: - tmp1 = (encalt & 0xfe0) << 2 - tmp2 = (encalt & 0x010) << 1 - - else: - tmp1 = (encalt & 0xff8) << 1 - tmp2 = 0 + if bit13 is True: + tmp1 = (encalt & 0xfe0) << 2 + tmp2 = (encalt & 0x010) << 1 + else: + tmp1 = (encalt & 0xff8) << 1 + tmp2 = 0 - return (encalt & 0x0F) | tmp1 | tmp2 | (mbit << 6) | (qbit << 4) + return (encalt & 0x0F) | tmp1 | tmp2 | (mbit << 6) | (qbit << 4) if __name__ == "__main__": - try: - for alt in range(-1000, 101400, 25): - dec = decode_alt(encode_alt_modes(alt, False), False) - if dec != alt: - print "Failure at %i with bit13 clear (got %s)" % (alt, dec) - for alt in range(-1000, 101400, 25): - dec = decode_alt(encode_alt_modes(alt, True), True) - if dec != alt: - print "Failure at %i with bit13 set (got %s)" % (alt, dec) - except MetricAltError: - print "Failure at %i due to metric alt bit" % alt + try: + for alt in range(-1000, 101400, 25): + dec = decode_alt(encode_alt_modes(alt, False), False) + if dec != alt: + print("Failure at %i with bit13 clear (got %s)" % (alt, dec)) + for alt in range(-1000, 101400, 25): + dec = decode_alt(encode_alt_modes(alt, True), True) + if dec != alt: + print("Failure at %i with bit13 set (got %s)" % (alt, dec)) + except MetricAltError: + print("Failure at %i due to metric alt bit" % alt) diff --git a/python/az_map.py b/python/az_map.py index 0481945..cfcce83 100755 --- a/python/az_map.py +++ b/python/az_map.py @@ -25,7 +25,6 @@ from PyQt4 import QtCore, QtGui import threading import math -import air_modes from air_modes.exceptions import * import numpy as np diff --git a/python/cpr.py b/python/cpr.py index 1e68f75..1612250 100755 --- a/python/cpr.py +++ b/python/cpr.py @@ -31,302 +31,302 @@ latz = 15 def nz(ctype): - return 4 * latz - ctype + return 4 * latz - ctype def dlat(ctype, surface): - if surface == 1: - tmp = 90.0 - else: - tmp = 360.0 + if surface == 1: + tmp = 90.0 + else: + tmp = 360.0 - nzcalc = nz(ctype) - if nzcalc == 0: - return tmp - else: - return tmp / nzcalc + nzcalc = nz(ctype) + if nzcalc == 0: + return tmp + else: + return tmp / nzcalc def nl(declat_in): - if abs(declat_in) >= 87.0: - return 1.0 - return math.floor( (2.0*math.pi) * math.acos(1.0- (1.0-math.cos(math.pi/(2.0*latz))) / math.cos( (math.pi/180.0)*abs(declat_in) )**2 )**-1) + if abs(declat_in) >= 87.0: + return 1.0 + return math.floor( (2.0*math.pi) * math.acos(1.0- (1.0-math.cos(math.pi/(2.0*latz))) / math.cos( (math.pi/180.0)*abs(declat_in) )**2 )**-1) def dlon(declat_in, ctype, surface): - if surface: - tmp = 90.0 - else: - tmp = 360.0 - nlcalc = max(nl(declat_in)-ctype, 1) - return tmp / nlcalc + if surface: + tmp = 90.0 + else: + tmp = 360.0 + nlcalc = max(nl(declat_in)-ctype, 1) + return tmp / nlcalc def decode_lat(enclat, ctype, my_lat, surface): - tmp1 = dlat(ctype, surface) - tmp2 = float(enclat) / (2**17) - j = math.floor(my_lat/tmp1) + math.floor(0.5 + ((my_lat % tmp1) / tmp1) - tmp2) + tmp1 = dlat(ctype, surface) + tmp2 = float(enclat) / (2**17) + j = math.floor(my_lat/tmp1) + math.floor(0.5 + ((my_lat % tmp1) / tmp1) - tmp2) - return tmp1 * (j + tmp2) + return tmp1 * (j + tmp2) def decode_lon(declat, enclon, ctype, my_lon, surface): - tmp1 = dlon(declat, ctype, surface) - tmp2 = float(enclon) / (2**17) - m = math.floor(my_lon / tmp1) + math.floor(0.5 + ((my_lon % tmp1) / tmp1) - tmp2) + tmp1 = dlon(declat, ctype, surface) + tmp2 = float(enclon) / (2**17) + m = math.floor(my_lon / tmp1) + math.floor(0.5 + ((my_lon % tmp1) / tmp1) - tmp2) - return tmp1 * (m + tmp2) + return tmp1 * (m + tmp2) def cpr_resolve_local(my_location, encoded_location, ctype, surface): - [my_lat, my_lon] = my_location - [enclat, enclon] = encoded_location + [my_lat, my_lon] = my_location + [enclat, enclon] = encoded_location - decoded_lat = decode_lat(enclat, ctype, my_lat, surface) - decoded_lon = decode_lon(decoded_lat, enclon, ctype, my_lon, surface) + decoded_lat = decode_lat(enclat, ctype, my_lat, surface) + decoded_lon = decode_lon(decoded_lat, enclon, ctype, my_lon, surface) - return [decoded_lat, decoded_lon] + return [decoded_lat, decoded_lon] def cpr_resolve_global(evenpos, oddpos, mypos, mostrecent, surface): - #cannot resolve surface positions unambiguously without knowing receiver position - if surface and mypos is None: - raise CPRNoPositionError - - dlateven = dlat(0, surface) - dlatodd = dlat(1, surface) - - evenpos = [float(evenpos[0]), float(evenpos[1])] - oddpos = [float(oddpos[0]), float(oddpos[1])] - - j = math.floor(((nz(1)*evenpos[0] - nz(0)*oddpos[0])/2**17) + 0.5) #latitude index - - rlateven = dlateven * ((j % nz(0))+evenpos[0]/2**17) - rlatodd = dlatodd * ((j % nz(1))+ oddpos[0]/2**17) - - #limit to -90, 90 - if rlateven > 270.0: - rlateven -= 360.0 - if rlatodd > 270.0: - rlatodd -= 360.0 - - #This checks to see if the latitudes of the reports straddle a transition boundary - #If so, you can't get a globally-resolvable location. - if nl(rlateven) != nl(rlatodd): - raise CPRBoundaryStraddleError - - if mostrecent == 0: - rlat = rlateven - else: - rlat = rlatodd - - #disambiguate latitude - if surface: - if mypos[0] < 0: - rlat -= 90 - - dl = dlon(rlat, mostrecent, surface) - nl_rlat = nl(rlat) - - m = math.floor(((evenpos[1]*(nl_rlat-1)-oddpos[1]*nl_rlat)/2**17)+0.5) #longitude index - - #when surface positions straddle a disambiguation boundary (90 degrees), - #surface decoding will fail. this might never be a problem in real life, but it'll fail in the - #test case. the documentation doesn't mention it. - - if mostrecent == 0: - enclon = evenpos[1] - else: - enclon = oddpos[1] - - rlon = dl * ((m % max(nl_rlat-mostrecent,1)) + enclon/2.**17) - - #print "DL: %f nl: %f m: %f rlon: %f" % (dl, nl_rlat, m, rlon) - #print "evenpos: %x, oddpos: %x, mostrecent: %i" % (evenpos[1], oddpos[1], mostrecent) - - if surface: - #longitudes need to be resolved to the nearest 90 degree segment to the receiver. - wat = mypos[1] - if wat < 0: - wat += 360 - zone = lambda lon: 90 * (int(lon) / 90) - rlon += (zone(wat) - zone(rlon)) - - #limit to (-180, 180) - if rlon > 180: - rlon -= 360.0 - - return [rlat, rlon] + #cannot resolve surface positions unambiguously without knowing receiver position + if surface and mypos is None: + raise CPRNoPositionError + + dlateven = dlat(0, surface) + dlatodd = dlat(1, surface) + + evenpos = [float(evenpos[0]), float(evenpos[1])] + oddpos = [float(oddpos[0]), float(oddpos[1])] + + j = math.floor(((nz(1)*evenpos[0] - nz(0)*oddpos[0])/2**17) + 0.5) #latitude index + + rlateven = dlateven * ((j % nz(0))+evenpos[0]/2**17) + rlatodd = dlatodd * ((j % nz(1))+ oddpos[0]/2**17) + + #limit to -90, 90 + if rlateven > 270.0: + rlateven -= 360.0 + if rlatodd > 270.0: + rlatodd -= 360.0 + + #This checks to see if the latitudes of the reports straddle a transition boundary + #If so, you can't get a globally-resolvable location. + if nl(rlateven) != nl(rlatodd): + raise CPRBoundaryStraddleError + + if mostrecent == 0: + rlat = rlateven + else: + rlat = rlatodd + + #disambiguate latitude + if surface: + if mypos[0] < 0: + rlat -= 90 + + dl = dlon(rlat, mostrecent, surface) + nl_rlat = nl(rlat) + + m = math.floor(((evenpos[1]*(nl_rlat-1)-oddpos[1]*nl_rlat)/2**17)+0.5) #longitude index + + #when surface positions straddle a disambiguation boundary (90 degrees), + #surface decoding will fail. this might never be a problem in real life, but it'll fail in the + #test case. the documentation doesn't mention it. + + if mostrecent == 0: + enclon = evenpos[1] + else: + enclon = oddpos[1] + + rlon = dl * ((m % max(nl_rlat-mostrecent,1)) + enclon/2.**17) + + #print "DL: %f nl: %f m: %f rlon: %f" % (dl, nl_rlat, m, rlon) + #print "evenpos: %x, oddpos: %x, mostrecent: %i" % (evenpos[1], oddpos[1], mostrecent) + + if surface: + #longitudes need to be resolved to the nearest 90 degree segment to the receiver. + wat = mypos[1] + if wat < 0: + wat += 360 + zone = lambda lon: 90 * (int(lon) / 90) + rlon += (zone(wat) - zone(rlon)) + + #limit to (-180, 180) + if rlon > 180: + rlon -= 360.0 + + return [rlat, rlon] #calculate range and bearing between two lat/lon points #should probably throw this in the mlat py somewhere or make another lib def range_bearing(loc_a, loc_b): - [a_lat, a_lon] = loc_a - [b_lat, b_lon] = loc_b + [a_lat, a_lon] = loc_a + [b_lat, b_lon] = loc_b - esquared = (1/298.257223563)*(2-(1/298.257223563)) - earth_radius_mi = 3963.19059 * (math.pi / 180) + esquared = (1/298.257223563)*(2-(1/298.257223563)) + earth_radius_mi = 3963.19059 * (math.pi / 180) - delta_lat = b_lat - a_lat - delta_lon = b_lon - a_lon + delta_lat = b_lat - a_lat + delta_lon = b_lon - a_lon - avg_lat = ((a_lat + b_lat) / 2.0) * math.pi / 180 + avg_lat = ((a_lat + b_lat) / 2.0) * math.pi / 180 - R1 = earth_radius_mi*(1.0-esquared)/pow((1.0-esquared*pow(math.sin(avg_lat),2)),1.5) + R1 = earth_radius_mi*(1.0-esquared)/pow((1.0-esquared*pow(math.sin(avg_lat),2)),1.5) - R2 = earth_radius_mi/math.sqrt(1.0-esquared*pow(math.sin(avg_lat),2)) + R2 = earth_radius_mi/math.sqrt(1.0-esquared*pow(math.sin(avg_lat),2)) - distance_North = R1*delta_lat - distance_East = R2*math.cos(avg_lat)*delta_lon + distance_North = R1*delta_lat + distance_East = R2*math.cos(avg_lat)*delta_lon - bearing = math.atan2(distance_East,distance_North) * (180.0 / math.pi) - if bearing < 0.0: - bearing += 360.0 + bearing = math.atan2(distance_East,distance_North) * (180.0 / math.pi) + if bearing < 0.0: + bearing += 360.0 - rnge = math.hypot(distance_East,distance_North) - return [rnge, bearing] + rnge = math.hypot(distance_East,distance_North) + return [rnge, bearing] class cpr_decoder: - def __init__(self, my_location): - self.my_location = my_location - self.evenlist = {} - self.oddlist = {} - self.evenlist_sfc = {} - self.oddlist_sfc = {} - - def set_location(self, new_location): - self.my_location = new_location - - def weed_poslists(self): - for poslist in [self.evenlist, self.oddlist]: - for key, item in poslist.items(): - if time.time() - item[2] > 10: - del poslist[key] - for poslist in [self.evenlist_sfc, self.oddlist_sfc]: - for key, item in poslist.items(): - if time.time() - item[2] > 25: - del poslist[key] - - def decode(self, icao24, encoded_lat, encoded_lon, cpr_format, surface): - if surface: - oddlist = self.oddlist_sfc - evenlist = self.evenlist_sfc - else: - oddlist = self.oddlist - evenlist = self.evenlist - - #add the info to the position reports list for global decoding - if cpr_format==1: - oddlist[icao24] = [encoded_lat, encoded_lon, time.time()] - else: - evenlist[icao24] = [encoded_lat, encoded_lon, time.time()] - - [decoded_lat, decoded_lon] = [None, None] - - #okay, let's traverse the lists and weed out those entries that are older than 10 seconds - self.weed_poslists() - - if (icao24 in evenlist) \ - and (icao24 in oddlist): - newer = (oddlist[icao24][2] - evenlist[icao24][2]) > 0 #figure out which report is newer - [decoded_lat, decoded_lon] = cpr_resolve_global(evenlist[icao24][0:2], oddlist[icao24][0:2], self.my_location, newer, surface) #do a global decode - else: - raise CPRNoPositionError - - if self.my_location is not None: - [rnge, bearing] = range_bearing(self.my_location, [decoded_lat, decoded_lon]) - else: - rnge = None - bearing = None - - return [decoded_lat, decoded_lon, rnge, bearing] + def __init__(self, my_location): + self.my_location = my_location + self.evenlist = {} + self.oddlist = {} + self.evenlist_sfc = {} + self.oddlist_sfc = {} + + def set_location(self, new_location): + self.my_location = new_location + + def weed_poslists(self): + for poslist in [self.evenlist, self.oddlist]: + for key, item in poslist.items(): + if time.time() - item[2] > 10: + del poslist[key] + for poslist in [self.evenlist_sfc, self.oddlist_sfc]: + for key, item in poslist.items(): + if time.time() - item[2] > 25: + del poslist[key] + + def decode(self, icao24, encoded_lat, encoded_lon, cpr_format, surface): + if surface: + oddlist = self.oddlist_sfc + evenlist = self.evenlist_sfc + else: + oddlist = self.oddlist + evenlist = self.evenlist + + #add the info to the position reports list for global decoding + if cpr_format==1: + oddlist[icao24] = [encoded_lat, encoded_lon, time.time()] + else: + evenlist[icao24] = [encoded_lat, encoded_lon, time.time()] + + [decoded_lat, decoded_lon] = [None, None] + + #okay, let's traverse the lists and weed out those entries that are older than 10 seconds + self.weed_poslists() + + if (icao24 in evenlist) \ + and (icao24 in oddlist): + newer = (oddlist[icao24][2] - evenlist[icao24][2]) > 0 #figure out which report is newer + [decoded_lat, decoded_lon] = cpr_resolve_global(evenlist[icao24][0:2], oddlist[icao24][0:2], self.my_location, newer, surface) #do a global decode + else: + raise CPRNoPositionError + + if self.my_location is not None: + [rnge, bearing] = range_bearing(self.my_location, [decoded_lat, decoded_lon]) + else: + rnge = None + bearing = None + + return [decoded_lat, decoded_lon, rnge, bearing] #encode CPR position def cpr_encode(lat, lon, ctype, surface): - if surface is True: - scalar = 2.**19 - else: - scalar = 2.**17 + if surface is True: + scalar = 2.**19 + else: + scalar = 2.**17 - #encode using 360 constant for segment size. - dlati = dlat(ctype, False) - yz = math.floor(scalar * ((lat % dlati)/dlati) + 0.5) - rlat = dlati * ((yz / scalar) + math.floor(lat / dlati)) + #encode using 360 constant for segment size. + dlati = dlat(ctype, False) + yz = math.floor(scalar * ((lat % dlati)/dlati) + 0.5) + rlat = dlati * ((yz / scalar) + math.floor(lat / dlati)) - #encode using 360 constant for segment size. - dloni = dlon(lat, ctype, False) - xz = math.floor(scalar * ((lon % dloni)/dloni) + 0.5) + #encode using 360 constant for segment size. + dloni = dlon(lat, ctype, False) + xz = math.floor(scalar * ((lon % dloni)/dloni) + 0.5) - yz = int(yz) & (2**17-1) - xz = int(xz) & (2**17-1) + yz = int(yz) & (2**17-1) + xz = int(xz) & (2**17-1) - return (yz, xz) #lat, lon + return (yz, xz) #lat, lon if __name__ == '__main__': - import sys, random - - rounds = 10001 - threshold = 1e-3 #0.001 deg lat/lon - #this accuracy is highly dependent on latitude, since at high - #latitudes the corresponding error in longitude is greater - - bs = 0 - surface = False - - lats = [i/(rounds/170.)-85 for i in range(0,rounds)] - lons = [i/(rounds/360.)-180 for i in range(0,rounds)] - - for i in range(0, rounds): - even_lat = lats[i] - #even_lat = random.uniform(-85, 85) - even_lon = lons[i] - #even_lon = random.uniform(-180, 180) - odd_lat = even_lat + 1e-3 - odd_lon = min(even_lon + 1e-3, 180) - decoder = cpr_decoder([odd_lat, odd_lon]) - - #encode that position - (evenenclat, evenenclon) = cpr_encode(even_lat, even_lon, False, surface) - (oddenclat, oddenclon) = cpr_encode(odd_lat, odd_lon, True, surface) - - #try to perform a global decode -- this should fail since the decoder - #only has heard one position. need two for global decoding. - icao = random.randint(0, 0xffffff) - try: - evenpos = decoder.decode(icao, evenenclat, evenenclon, False, surface) - raise Exception("CPR test failure: global decode with only one report") - except CPRNoPositionError: - pass - - #now try to do a real decode with the last packet's odd complement - #watch for a boundary straddle -- this isn't fatal, it just indicates - #that the even and odd reports lie on either side of a longitudinal boundary - #and so you can't get a position - try: - (odddeclat, odddeclon, rng, brg) = decoder.decode(icao, oddenclat, oddenclon, True, surface) - except CPRBoundaryStraddleError: - bs += 1 - continue - except CPRNoPositionError: - raise Exception("CPR test failure: no decode after even/odd inputs") - - if abs(odddeclat - odd_lat) > threshold or abs(odddeclon - odd_lon) > threshold: - print "F odddeclat: %f odd_lat: %f" % (odddeclat, odd_lat) - print "F odddeclon: %f odd_lon: %f" % (odddeclon, odd_lon) - raise Exception("CPR test failure: global decode error greater than threshold") -# else: -# print "S odddeclat: %f odd_lat: %f" % (odddeclat, odd_lat) -# print "S odddeclon: %f odd_lon: %f" % (odddeclon, odd_lon) - - nexteven_lat = odd_lat + 1e-3 - nexteven_lon = min(odd_lon + 1e-3, 180) - - (nexteven_enclat, nexteven_enclon) = cpr_encode(nexteven_lat, nexteven_lon, False, surface) - - #try a locally-referenced decode - try: - (evendeclat, evendeclon) = cpr_resolve_local([even_lat, even_lon], [nexteven_enclat, nexteven_enclon], False, surface) - except CPRNoPositionError: - raise Exception("CPR test failure: local decode failure to resolve") - - #check to see if the positions were valid - if abs(evendeclat - nexteven_lat) > threshold or abs(evendeclon - nexteven_lon) > threshold: - print "F evendeclat: %f nexteven_lat: %f evenlat: %f" % (evendeclat, nexteven_lat, even_lat) - print "F evendeclon: %f nexteven_lon: %f evenlon: %f" % (evendeclon, nexteven_lon, even_lon) - raise Exception("CPR test failure: local decode error greater than threshold") - - print "CPR test successful. There were %i boundary straddles over %i rounds." % (bs, rounds) + import sys, random + + rounds = 10001 + threshold = 1e-3 #0.001 deg lat/lon + #this accuracy is highly dependent on latitude, since at high + #latitudes the corresponding error in longitude is greater + + bs = 0 + surface = False + + lats = [i/(rounds/170.)-85 for i in range(0,rounds)] + lons = [i/(rounds/360.)-180 for i in range(0,rounds)] + + for i in range(0, rounds): + even_lat = lats[i] + #even_lat = random.uniform(-85, 85) + even_lon = lons[i] + #even_lon = random.uniform(-180, 180) + odd_lat = even_lat + 1e-3 + odd_lon = min(even_lon + 1e-3, 180) + decoder = cpr_decoder([odd_lat, odd_lon]) + + #encode that position + (evenenclat, evenenclon) = cpr_encode(even_lat, even_lon, False, surface) + (oddenclat, oddenclon) = cpr_encode(odd_lat, odd_lon, True, surface) + + #try to perform a global decode -- this should fail since the decoder + #only has heard one position. need two for global decoding. + icao = random.randint(0, 0xffffff) + try: + evenpos = decoder.decode(icao, evenenclat, evenenclon, False, surface) + raise Exception("CPR test failure: global decode with only one report") + except CPRNoPositionError: + pass + + #now try to do a real decode with the last packet's odd complement + #watch for a boundary straddle -- this isn't fatal, it just indicates + #that the even and odd reports lie on either side of a longitudinal boundary + #and so you can't get a position + try: + (odddeclat, odddeclon, rng, brg) = decoder.decode(icao, oddenclat, oddenclon, True, surface) + except CPRBoundaryStraddleError: + bs += 1 + continue + except CPRNoPositionError: + raise Exception("CPR test failure: no decode after even/odd inputs") + + if abs(odddeclat - odd_lat) > threshold or abs(odddeclon - odd_lon) > threshold: + print("F odddeclat: %f odd_lat: %f" % (odddeclat, odd_lat)) + print( "F odddeclon: %f odd_lon: %f" % (odddeclon, odd_lon)) + raise Exception("CPR test failure: global decode error greater than threshold") +# else: +# print("S odddeclat: %f odd_lat: %f" % (odddeclat, odd_lat)) +# print("S odddeclon: %f odd_lon: %f" % (odddeclon, odd_lon)) + + nexteven_lat = odd_lat + 1e-3 + nexteven_lon = min(odd_lon + 1e-3, 180) + + (nexteven_enclat, nexteven_enclon) = cpr_encode(nexteven_lat, nexteven_lon, False, surface) + + #try a locally-referenced decode + try: + (evendeclat, evendeclon) = cpr_resolve_local([even_lat, even_lon], [nexteven_enclat, nexteven_enclon], False, surface) + except CPRNoPositionError: + raise Exception("CPR test failure: local decode failure to resolve") + + #check to see if the positions were valid + if abs(evendeclat - nexteven_lat) > threshold or abs(evendeclon - nexteven_lon) > threshold: + print("F evendeclat: %f nexteven_lat: %f evenlat: %f" % (evendeclat, nexteven_lat, even_lat)) + print("F evendeclon: %f nexteven_lon: %f evenlon: %f" % (evendeclon, nexteven_lon, even_lon)) + raise Exception("CPR test failure: local decode error greater than threshold") + + print("CPR test successful. There were %i boundary straddles over %i rounds." % (bs, rounds)) diff --git a/python/flightgear.py b/python/flightgear.py index 69c5f1a..3c6292a 100755 --- a/python/flightgear.py +++ b/python/flightgear.py @@ -24,7 +24,7 @@ def __init__(self, cprdec, hostname, port, pub): self._cpr = cprdec self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.sock.connect((self.hostname, self.port)) +# self.sock.connect((self.hostname, self.port)) pub.subscribe("type17_dl", self.output) def output(self, msg): @@ -69,7 +69,7 @@ def update(self, icao24): and (icao24 in self.velocities)\ and (icao24 in self.callsigns) if complete: - print "FG update: %s" % (self.callsigns[icao24][0]) + print("FG update: %s" % (self.callsigns[icao24][0])) msg = fg_posmsg(self.callsigns[icao24][0], self.callsigns[icao24][1], self.positions[icao24][0], @@ -80,7 +80,7 @@ def update(self, icao24): self.velocities[icao24][2], self.velocities[icao24][3]).pack() - self.sock.send(msg) + self.sock.sendto(msg, (self.hostname, self.port)) class fg_header: def __init__(self): @@ -119,7 +119,7 @@ def pack(self): "SMALL": 'Aircraft/CitationX/Models/Citation-X.xml', "LARGE": 'Aircraft/CRJ700-family/Models/CRJ700.xml', "LARGE HIGH VORTEX": 'Aircraft/757-200/Models/757-200.xml', - "HEAVY": 'Aircraft/747-200/Models/boeing747-200.xml', + "HEAVY": 'Aircraft/IDG-A32X/Models/A320neo-CFM.xml', "HIGH PERFORMANCE": 'Aircraft/SR71-BlackBird/Models/Blackbird-SR71B.xml', #yeah i know "ROTORCRAFT": 'Aircraft/ec130/Models/ec130b4.xml', "GLIDER": 'Aircraft/ASK21-MI/Models/ask21mi.xml', diff --git a/python/mlat.py b/python/mlat.py index 7c79a01..1583b1f 100755 --- a/python/mlat.py +++ b/python/mlat.py @@ -55,7 +55,8 @@ def wgs84_height(lat, lon): #convert ECEF to lat/lon/alt without geoid correction #returns alt in meters -def ecef2llh((x,y,z)): +def ecef2llh(ecef): + x, y, z = ecef ep = math.sqrt((wgs84_a2 - wgs84_b2) / wgs84_b2) p = math.sqrt(x**2+y**2) th = math.atan2(wgs84_a*z, wgs84_b*p) @@ -71,7 +72,8 @@ def ecef2llh((x,y,z)): #convert lat/lon/alt coords to ECEF without geoid correction, WGS84 model #remember that alt is in meters -def llh2ecef((lat, lon, alt)): +def llh2ecef(lla): + lat, lon, alt = lla lat *= (math.pi / 180.0) lon *= (math.pi / 180.0) @@ -84,7 +86,8 @@ def llh2ecef((lat, lon, alt)): return [x,y,z] #do both of the above to get a geoid-corrected x,y,z position -def llh2geoid((lat, lon, alt)): +def llh2geoid(lla): + lat, lon, alt = lla (x,y,z) = llh2ecef((lat, lon, alt + wgs84_height(lat, lon))) return [x,y,z] @@ -185,7 +188,7 @@ def mlat(replies, altitude): 10 + numpy.linalg.norm(testplane-numpy.array(llh2geoid(teststations[3]))) / c, ] - print teststamps + print(teststamps) replies = [] for i in range(0, len(teststations)): @@ -193,7 +196,7 @@ def mlat(replies, altitude): ans = mlat(replies, testalt) error = numpy.linalg.norm(numpy.array(llh2ecef(ans))-numpy.array(testplane)) range = numpy.linalg.norm(llh2geoid(ans)-numpy.array(testme)) - print testplane-testme - print ans - print "Error: %.2fm" % (error) - print "Range: %.2fkm (from first station in list)" % (range/1000) + print(testplane-testme) + print(ans) + print("Error: %.2fm" % (error)) + print("Range: %.2fkm (from first station in list)" % (range/1000)) diff --git a/python/mlat_types.py b/python/mlat_types.py deleted file mode 100644 index 8b13789..0000000 --- a/python/mlat_types.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/python/types.py b/python/modes_types.py similarity index 100% rename from python/types.py rename to python/modes_types.py diff --git a/python/msprint.py b/python/msprint.py index e2c8ff0..c7aa7aa 100644 --- a/python/msprint.py +++ b/python/msprint.py @@ -20,7 +20,6 @@ # import time, os, sys -from string import split, join import air_modes from air_modes.exceptions import * import math @@ -44,7 +43,7 @@ def prefix(msg): def _print(self, msg): if self._callback is None: - print msg + print(msg) else: self._callback(msg) diff --git a/python/parse.py b/python/parse.py index 4fd5832..86e8eab 100644 --- a/python/parse.py +++ b/python/parse.py @@ -20,8 +20,7 @@ # import time, os, sys -from string import split, join -from altitude import decode_alt +from air_modes.altitude import decode_alt import math import air_modes from air_modes.exceptions import * @@ -32,14 +31,14 @@ def __init__(self, data): self.data = data self.fields = self.parse() - types = { } + dtypes = { } offset = 1 #field offset applied to all fields. used for offsetting #subtypes to reconcile with the spec. Really just for readability. #get a particular field from the data def __getitem__(self, fieldname): mytype = self.get_type() - if mytype in self.types: + if mytype in self.dtypes: if fieldname in self.fields: #verify it exists in this packet type return self.fields[fieldname] else: @@ -52,9 +51,9 @@ def __getitem__(self, fieldname): def parse(self): fields = {} mytype = self.get_type() - if mytype in self.types: - for field in self.types[mytype]: - bits = self.types[self.get_type()][field] + if mytype in self.dtypes: + for field in self.dtypes[mytype]: + bits = self.dtypes[self.get_type()][field] if len(bits) == 3: obj = bits[2](self.get_bits(bits[0], bits[1])) fields.update(obj.parse()) @@ -93,7 +92,7 @@ def get_bits(self, *args): class bds09_reply(data_field): offset = 6 - types = { #BDS0,9 subtype 0 + dtypes = { #BDS0,9 subtype 0 0: {"sub": (6,3), "dew": (10,1), "vew": (11,11), "dns": (22,1), "vns": (23,11), "str": (34,1), "tr": (35,6), "dvr": (41,1), "vr": (42,9)}, @@ -123,7 +122,7 @@ def get_numbits(self): class me_reply(data_field): #types in this format are listed by BDS register #TODO: add comments explaining these fields - types = { 0x05: {"ftc": (1,5), "ss": (6,2), "saf": (8,1), "alt": (9,12), "time": (21,1), "cpr": (22,1), "lat": (23,17), "lon": (40,17)}, #airborne position + dtypes = { 0x05: {"ftc": (1,5), "ss": (6,2), "saf": (8,1), "alt": (9,12), "time": (21,1), "cpr": (22,1), "lat": (23,17), "lon": (40,17)}, #airborne position 0x06: {"ftc": (1,5), "mvt": (6,7), "gts": (13,1), "gtk": (14,7), "time": (21,1), "cpr": (22,1), "lat": (23,17), "lon": (40,17)}, #surface position 0x07: {"ftc": (1,5),}, #TODO extended squitter status 0x08: {"ftc": (1,5), "cat": (6,3), "ident": (9,48)}, #extended squitter identification and type @@ -157,7 +156,7 @@ def get_numbits(self): #resolves the TCAS reply types from TTI info class tcas_reply(data_field): offset = 61 - types = { 0: {"tti": (61,2)}, #UNKNOWN + dtypes = { 0: {"tti": (61,2)}, #UNKNOWN 1: {"tti": (61,2), "tid": (63,26)}, 2: {"tti": (61,2), "tida": (63,13), "tidr": (76,7), "tidb": (83,6)} } @@ -171,7 +170,7 @@ def get_numbits(self): class mb_reply(data_field): offset = 33 #fields offset by 33 to match documentation #types are based on bds1 subfield - types = { 0: {"bds1": (33,4), "bds2": (37,4)}, #TODO + dtypes = { 0: {"bds1": (33,4), "bds2": (37,4)}, #TODO 1: {"bds1": (33,4), "bds2": (37,4), "cfs": (41,4), "acs": (45,20), "bcs": (65,16), "ecs": (81,8)}, 2: {"bds1": (33,4), "bds2": (37,4), "ais": (41,48)}, 3: {"bds1": (33,4), "bds2": (37,4), "ara": (41,14), "rac": (55,4), "rat": (59,1), @@ -195,7 +194,7 @@ def get_numbits(self): class mv_reply(data_field): offset = 33 - types = { "ara": (41,14), "mte": (60,1), "rac": (55,4), "rat": (59,1), + dtypes = { "ara": (41,14), "mte": (60,1), "rac": (55,4), "rat": (59,1), "vds": (33,8), "vds1": (33,4), "vds2": (37,4) } @@ -211,7 +210,7 @@ def get_numbits(self): #the whole Mode S packet type class modes_reply(data_field): - types = { 0: {"df": (1,5), "vs": (6,1), "cc": (7,1), "sl": (9,3), "ri": (14,4), "ac": (20,13), "ap": (33,24)}, + dtypes = { 0: {"df": (1,5), "vs": (6,1), "cc": (7,1), "sl": (9,3), "ri": (14,4), "ac": (20,13), "ap": (33,24)}, 4: {"df": (1,5), "fs": (6,3), "dr": (9,5), "um": (14,6), "ac": (20,13), "ap": (33,24)}, 5: {"df": (1,5), "fs": (6,3), "dr": (9,5), "um": (14,6), "id": (20,13), "ap": (33,24)}, 11: {"df": (1,5), "ca": (6,3), "aa": (9,24), "pi": (33,24)}, diff --git a/python/qa_gr-air-modes.py b/python/qa_gr-air-modes.py deleted file mode 100755 index 8757814..0000000 --- a/python/qa_gr-air-modes.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2004,2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -import gr-air-modes_swig - -class qa_gr-air-modes (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_001_square_ff (self): - src_data = (-3, 4, -5.5, 2, 3) - expected_result = (9, 16, 30.25, 4, 9) - src = gr.vector_source_f (src_data) - sqr = gr-air-modes_swig.square_ff () - dst = gr.vector_sink_f () - self.tb.connect (src, sqr) - self.tb.connect (sqr, dst) - self.tb.run () - result_data = dst.data () - self.assertFloatTuplesAlmostEqual (expected_result, result_data, 6) - - def test_002_square2_ff (self): - src_data = (-3, 4, -5.5, 2, 3) - expected_result = (9, 16, 30.25, 4, 9) - src = gr.vector_source_f (src_data) - sqr = gr-air-modes_swig.square2_ff () - dst = gr.vector_sink_f () - self.tb.connect (src, sqr) - self.tb.connect (sqr, dst) - self.tb.run () - result_data = dst.data () - self.assertFloatTuplesAlmostEqual (expected_result, result_data, 6) - -if __name__ == '__main__': - gr_unittest.main () diff --git a/python/radio.py b/python/radio.py index a466629..fefb094 100644 --- a/python/radio.py +++ b/python/radio.py @@ -129,7 +129,7 @@ def set_freq(self, freq): def set_gain(self, gain): if self.live_source(): self._u.set_gain(gain) - print "Gain is %f" % self.get_gain() + print("Gain is %f" % self.get_gain()) return self.get_gain() def set_rate(self, rate): @@ -164,13 +164,19 @@ def _setup_source(self, options): if options.source == "uhd": #UHD source by default from gnuradio import uhd - self._u = uhd.single_usrp_source(options.args, uhd.io_type_t.COMPLEX_FLOAT32, 1) + self._u = uhd.usrp_source( + options.args, + uhd.stream_args( + cpu_format="fc32", + channels=range(1), + ), + ) if(options.subdev): self._u.set_subdev_spec(options.subdev, 0) if not self._u.set_center_freq(options.freq): - print "Failed to set initial frequency" + print("Failed to set initial frequency") #check for GPSDO #if you have a GPSDO, UHD will automatically set the timestamp to UTC time @@ -188,9 +194,9 @@ def _setup_source(self, options): g = self._u.get_gain_range() options.gain = (g.start()+g.stop()) / 2.0 - print "Setting gain to %i" % options.gain + print("Setting gain to %i" % options.gain) self._u.set_gain(options.gain) - print "Gain is %i" % self._u.get_gain() + print("Gain is %i" % self._u.get_gain()) #TODO: detect if you're using an RTLSDR or Jawbreaker #and set up accordingly. @@ -200,13 +206,13 @@ def _setup_source(self, options): # self._u.set_sample_rate(3.2e6) #fixed for RTL dongles self._u.set_sample_rate(options.rate) if not self._u.set_center_freq(options.freq): - print "Failed to set initial frequency" + print("Failed to set initial frequency") # self._u.set_gain_mode(0) #manual gain mode if options.gain is None: options.gain = 34 self._u.set_gain(options.gain) - print "Gain is %i" % self._u.get_gain() + print("Gain is %i" % self._u.get_gain()) #Note: this should only come into play if using an RTLSDR. # lpfiltcoeffs = gr.firdes.low_pass(1, 5*3.2e6, 1.6e6, 300e3) @@ -220,12 +226,12 @@ def _setup_source(self, options): except: raise Exception("Please input UDP source e.g. 192.168.10.1:12345") self._u = blocks.udp_source(gr.sizeof_gr_complex, ip, int(port)) - print "Using UDP source %s:%s" % (ip, port) + print("Using UDP source %s:%s" % (ip, port)) else: self._u = blocks.file_source(gr.sizeof_gr_complex, options.source) - print "Using file source %s" % options.source + print("Using file source %s" % options.source) - print "Rate is %i" % (options.rate,) + print("Rate is %i" % (options.rate,)) def close(self): self.stop() diff --git a/python/raw_server.py b/python/raw_server.py index 53fa67e..67f0e78 100644 --- a/python/raw_server.py +++ b/python/raw_server.py @@ -21,7 +21,6 @@ import time, os, sys, socket -from string import split, join from datetime import * class raw_server: @@ -41,12 +40,12 @@ def output(self, msg): conn.send(msg) except socket.error: self._conns.remove(conn) - print "Connections: ", len(self._conns) + print("Connections: ", len(self._conns)) def add_pending_conns(self): try: conn, addr = self._s.accept() self._conns.append(conn) - print "Connections: ", len(self._conns) + print("Connections: ", len(self._conns)) except socket.error: pass diff --git a/python/rx_path.py b/python/rx_path.py index 1b47585..41914c6 100644 --- a/python/rx_path.py +++ b/python/rx_path.py @@ -20,7 +20,6 @@ # from gnuradio import gr, blocks, filter -import air_modes_swig class rx_path(gr.hier_block2): diff --git a/python/sbs1.py b/python/sbs1.py index e4eb76a..c3a4bd3 100644 --- a/python/sbs1.py +++ b/python/sbs1.py @@ -21,7 +21,6 @@ import time, os, sys, socket -from string import split, join import air_modes import datetime from air_modes.exceptions import * @@ -98,7 +97,7 @@ def output(self, msg): conn.send(sbs1_msg) except socket.error: self._conns.remove(conn) - print "Connections: ", len(self._conns) + print("Connections: ", len(self._conns)) except ADSBError: pass @@ -106,7 +105,7 @@ def add_pending_conns(self): try: conn, addr = self._s.accept() self._conns.append(conn) - print "Connections: ", len(self._conns) + print("Connections: ", len(self._conns)) except socket.error: pass diff --git a/python/sql.py b/python/sql.py index c8a856f..99ffbdb 100644 --- a/python/sql.py +++ b/python/sql.py @@ -20,7 +20,6 @@ # import time, os, sys, threading -from string import split, join import air_modes import sqlite3 from air_modes.exceptions import * diff --git a/python/zmq_socket.py b/python/zmq_socket.py index f379427..802e9f7 100644 --- a/python/zmq_socket.py +++ b/python/zmq_socket.py @@ -27,13 +27,13 @@ import threading import zmq from gnuradio.gr.pubsub import pubsub -import Queue +import queue class zmq_pubsub_iface(threading.Thread): def __init__(self, context, subaddr=None, pubaddr=None): threading.Thread.__init__(self) #private data - self._queue = Queue.Queue() + self._queue = queue.queue() self._subsocket = context.socket(zmq.SUB) self._pubsocket = context.socket(zmq.PUB) self._subaddr = subaddr @@ -114,7 +114,7 @@ def close(self): self.finished.wait(0.2) def pr(x): - print x + print(x) if __name__ == "__main__": #create socket pair diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt index 495e6d4..3c8f15a 100644 --- a/swig/CMakeLists.txt +++ b/swig/CMakeLists.txt @@ -31,13 +31,10 @@ include(GrPython) ######################################################################## # Setup swig generation ######################################################################## -foreach(incdir ${GNURADIO_RUNTIME_INCLUDE_DIRS}) - list(APPEND GR_SWIG_INCLUDE_DIRS ${incdir}/gnuradio/swig) -endforeach(incdir) +set(GR_SWIG_INCLUDE_DIRS $) +set(GR_SWIG_TARGET_DEPS gnuradio::runtime_swig) set(GR_SWIG_LIBRARIES air_modes) -#set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/gr-air-modes_swig_doc.i) -#set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include) GR_SWIG_MAKE(air_modes_swig air_modes_swig.i)