summaryrefslogtreecommitdiff
path: root/gr-qtgui/python/qtgui/azelplot.py
diff options
context:
space:
mode:
Diffstat (limited to 'gr-qtgui/python/qtgui/azelplot.py')
-rw-r--r--gr-qtgui/python/qtgui/azelplot.py128
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()
+