summaryrefslogtreecommitdiff
path: root/gr-qtgui/python/qtgui/distanceradar.py
blob: 5659045c27b3f34f708d55d3bc77140771674d92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/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
#
#

import sys
from PyQt5 import QtWidgets
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
    
from gnuradio import gr
import pmt

class DistanceRadar(gr.sync_block, FigureCanvas):
    """
    This block creates a radar-like screen used to represent distance or size.
    This can be used in many ways such as circles closer to the center are
    closer, or just the opposite where closer to the center is smaller.

    Note: Incoming values should range between 0 (center bullseye) and
    100 (all the way out)
    """
    def __init__(self, lbl, ticklabels, backgroundColor, fontColor, ringColor, Parent=None,
                 width=4, height=4, dpi=100):
        gr.sync_block.__init__(self, name="distanceradar", in_sig=None, out_sig=None)

        self.lbl = lbl

        self.message_port_register_in(pmt.intern("radius"))
        self.set_msg_handler(pmt.intern("radius"), self.msgHandler)

        self.fontColor = fontColor
        self.backgroundColor = backgroundColor
        self.ringColor = ringColor

        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 100 to set the max for the plot
        self.axes.plot(np.linspace(0, 2*np.pi, 100), np.ones(100)*100, color=self.fontColor,
                       linestyle='')

        # Plot line: Initialize out to 100 and blank
        radius = 100
        self.blackline = self.axes.plot(np.linspace(0, 2*np.pi, 100), np.ones(100)*radius,
                                        color=self.fontColor, linestyle='-')
        self.redline = None

        self.filledcircle = None
        # Create bullseye
        circle = plt.Circle((0.0, 0.0), 20, transform=self.axes.transData._b, color=self.fontColor,
                            alpha=0.4)
        self.bullseye = self.axes.add_artist(circle)

        # Rotate zero up
        self.axes.set_theta_zero_location("N")

        self.axes.set_yticklabels(ticklabels, color=self.fontColor)
        self.axes.set_xticklabels([], color=self.fontColor)

        FigureCanvas.__init__(self, self.fig)
        self.setParent(Parent)


        self.title = self.fig.suptitle(self.lbl, fontsize=8, fontweight='bold',
                                        color=self.fontColor)

        FigureCanvas.setSizePolicy(self,
                                   QtWidgets.QSizePolicy.Expanding,
                                   QtWidgets.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

    def msgHandler(self, msg):
        try:
            new_val = pmt.to_python(pmt.cdr(msg))

            if type(new_val) == float or type(new_val) == int:
                self.updateData(new_val)
            else:
                gr.log.error("Value received was not an int or a "
                      "float: %s" % str(type(new_val)))

        except Exception as e:
            gr.log.error("Error with message conversion: %s" % str(e))

    def updateData(self, radius):
        if self.redline is not None:
            self.redline.pop(0).remove()
        self.redline = self.axes.plot(np.linspace(0, 2*np.pi, 100), np.ones(100)*radius,
                                      color='r', linestyle='-')

        if self.filledcircle:
            self.filledcircle.remove()

        self.bullseye.remove()
        circle = plt.Circle((0.0, 0.0), radius, transform=self.axes.transData._b,
                            color=self.ringColor, alpha=0.4)
        self.filledcircle = self.axes.add_artist(circle)
        # Create bullseye
        circle = plt.Circle((0.0, 0.0), 20, transform=self.axes.transData._b,
                            color=self.fontColor, alpha=0.4)
        self.bullseye = self.axes.add_artist(circle)

        self.draw()