diff options
Diffstat (limited to 'gr-qtgui/python/qtgui/azelplot.py')
-rw-r--r-- | gr-qtgui/python/qtgui/azelplot.py | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/gr-qtgui/python/qtgui/azelplot.py b/gr-qtgui/python/qtgui/azelplot.py new file mode 100644 index 0000000000..d23d39234d --- /dev/null +++ b/gr-qtgui/python/qtgui/azelplot.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from PyQt5 import QtWidgets +import numpy as np +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.figure import Figure +import math + +from gnuradio import gr +import pmt + +class AzElPlot(gr.sync_block, FigureCanvas): + """ + This block creates a polar plot with azimuth represented as the angle + clockwise around the circle, and elevation represented as the radius. + 90 degrees elevation is center (directly overhead), + while the horizon (0 degrees) is the outside circe. Note that if an + elevation < 0 is provided, the marker will turn to an open circle + on the perimeter at the specified azimuth angle. + """ + def __init__(self, lbl, backgroundColor, dotColor, Parent=None, + width=4, height=4, dpi=90): + gr.sync_block.__init__(self, name = "MsgPushButton", in_sig = None, + out_sig = None) + + self.lbl = lbl + + self.message_port_register_in(pmt.intern("azel")) + self.set_msg_handler(pmt.intern("azel"), self.msgHandler) + + self.dotColor = dotColor + self.backgroundColor = backgroundColor + self.scaleColor = 'black' + if (self.backgroundColor == 'black'): + self.scaleColor = 'white' + + self.fig = Figure(figsize=(width, height), dpi=dpi) + self.fig.patch.set_facecolor(self.backgroundColor) + + self.axes = self.fig.add_subplot(111, polar=True, facecolor=self.backgroundColor) + + # Create an "invisible" line at 90 to set the max for the plot + self.axes.plot(np.linspace(0, 2*np.pi, 90), np.ones(90)*90, color=self.scaleColor, + linestyle='') + + # Plot line: Initialize out to 90 and blank + radius = 90 + self.blackline = self.axes.plot(np.linspace(0, 2*np.pi, 90), np.ones(90)*radius, + color=self.scaleColor, linestyle='-') + self.reddot = None + + # Rotate zero up + self.axes.set_theta_zero_location("N") + + # Set limits: + self.axes.set_rlim(0, 90) + + self.axes.set_yticklabels([], color=self.scaleColor) + self.axes.set_xticklabels(['0', '315', '270', '225', '180', '135', '90', '45'], + color=self.scaleColor) + + FigureCanvas.__init__(self, self.fig) + self.setParent(Parent) + + self.title = self.fig.suptitle(self.lbl, fontsize=8, fontweight='bold', color='black') + + FigureCanvas.setSizePolicy(self, + QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Expanding) + + self.setMinimumSize(240, 230) + FigureCanvas.updateGeometry(self) + + def msgHandler(self, msg): + new_val = None + + try: + new_val = pmt.to_python(pmt.car(msg)) + if new_val is not None: + if type(new_val) == dict: + if 'az' in new_val and 'el' in new_val: + self.updateData(float(new_val['az']), float(new_val['el'])) + else: + gr.log.error("az and el keys were not found in the dictionary.") + else: + gr.log.error("Value received was not a dictionary. Expecting a dictionary " + "in the car message component with az and el keys.") + else: + gr.log.error("The CAR section of the inbound message was None. " + "This part should contain the dictionary with 'az' and 'el' float keys.") + except Exception as e: + gr.log.error("[AzElPlot] Error with message conversion: %s" % str(e)) + if new_val is not None: + gr.log.error(str(new_val)) + + def updateData(self, azimuth, elevation): + if self.reddot is not None: + self.reddot.pop(0).remove() + + # Plot is angle, radius where angle is in radians + + if (elevation > 0): + # Need to reverse elevation. 90 degrees is center (directly overhead), + # and 90 degrees is horizon. + if (elevation > 90.0): + elevation = 90.0 + + convertedElevation = 90.0 - elevation + # Note: +azimuth for the plot is measured counter-clockwise, so need to reverse it. + self.reddot = self.axes.plot(-azimuth * math.pi/180.0, convertedElevation, self.dotColor, + markersize=8) + else: + # It's below the horizon. Show an open circle at the perimeter + elevation = 0.0 + self.reddot = self.axes.plot(-azimuth * math.pi/180.0, 89.0, self.dotColor, + markerfacecolor="None", markersize=16, fillstyle=None) + + self.draw() + |