Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dependency and mod compass block #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# About gr-doa
gr-doa is a demonstration on the phase synchronization capability of Ettus Research's TwinRX daughtercards.
TwinRX daughtercards can achieve a high degree of accurate phase synchronization except for constant
repeatable relative phase offsets. We provide apps to determine the accuracy of phase synchronization achieved
and to estimate DoA which fundamentally requires accurate phase synchronization
gr-doa is a demonstration on the phase synchronization capability of Ettus Research's TwinRX daughtercards.
TwinRX daughtercards can achieve a high degree of accurate phase synchronization except for constant
repeatable relative phase offsets. We provide apps to determine the accuracy of phase synchronization achieved
and to estimate DoA which fundamentally requires accurate phase synchronization
across the receive streams.

### Basic Dependencies
- UHD >= 3.10.1.0
- gnuradio >= 3.7.10.1
- armadillo >= 7.300
- SWIG >= 3.0.8

### Dependencies Needed for QA Testing
- octave (Tested 4.0.2)
Expand All @@ -24,11 +25,11 @@ across the receive streams.
- Relative phase offset measurement and correction
- Antenna element calibration for linear arrays
- MUSIC algorithm for linear arrays
- Root-MUSIC algorithm for linear arrays
- Root-MUSIC algorithm for linear arrays

### OSs Tested
- Ubuntu 14.04, Ubuntu 16.04

### OSs Tested
- Ubuntu 14.04, Ubuntu 16.04

### Installation
`$ git clone https://github.com/EttusResearch/gr-doa` <br />
`$ cd gr-doa` <br />
Expand Down
11 changes: 9 additions & 2 deletions grc/doa_qt_compass.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<category>DoA</category>
<import>import doa</import>
<make>#set $win2 = 'self.%s.this_layout'%$id
doa.compass($name, $min_val, $max_val, $step, $arc_bias)
doa.compass($name, $min_val, $max_val, $step, $arc_bias, $needle_N)
$(gui_hint()($win2))</make>

<param>
Expand Down Expand Up @@ -52,7 +52,12 @@ $(gui_hint()($win2))</make>
<value>0</value>
<type>float</type>
</param>

<param>
<name>Number of Needles</name>
<key>needle_N</key>
<value>1</value>
<type>int</type>
</param>
<param>
<name>GUI Hint</name>
<key>gui_hint</key>
Expand All @@ -65,6 +70,7 @@ $(gui_hint()($win2))</make>
<sink>
<name>in</name>
<type>float</type>
<nports>$needle_N</nports>
</sink>

<doc>
Expand All @@ -75,5 +81,6 @@ min_val: Min. value displayed on the compass.
max_val: Max. value displayed on the compass.
step: Step-size.
arc_bias: Clockwise rotation applied to dial.
needle_N: Number of needles displayed on the compass.
</doc>
</block>
125 changes: 63 additions & 62 deletions python/compass.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,78 @@
class compass(gr.sync_block, Qwt.QwtPlot):
__pyqtSignals__ = ("updatePlot(int)")

def __init__(self, label="", min_val=-90, max_val=90, step=10, arc_bias=0, *args):
gr.sync_block.__init__(self,name="QT Compass",in_sig=[numpy.float32],out_sig=[])
def __init__(self, label="", min_val=-90, max_val=90, step=10, arc_bias=0, needle_N=1, *args):
gr.sync_block.__init__(self,name="QT Compass",in_sig=[numpy.float32]*needle_N,out_sig=[])
Qwt.QwtPlot.__init__(self, *args)

# Set parameters
self.update_period = 0.1
self.last = time.time()
self.next_angle = 0
self.next_angles = []

### QT STUFF

# Setup overall layouts
self.this_layout = Qt.QVBoxLayout()
self.compass_layout = Qt.QGridLayout()

# Setup Dial
self.dial = Qwt.QwtDial(self)
self.dial.setOrigin(180+arc_bias) # Orient dial so 0 is at 9 o'clock
self.dial.setScaleArc(min_val,max_val)
self.dial.setRange(min_val, max_val, step)
self.dial.setScale(min_val ,max_val, step)
self.dial.setScaleTicks(1,20,30)

# Add needle
self.dial.setNeedle(Qwt.QwtDialSimpleNeedle(
Qwt.QwtDialSimpleNeedle.Arrow,
True,
QtGui.QColor(QtCore.Qt.red),
QtGui.QColor(QtCore.Qt.gray).light(130)))
self.dial.setValue(0)

# Set sizing
self.dial.setMinimumSize(250,250)
self.dial.setSizePolicy(Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Expanding)
# Setup Dials
self.dial_list = []
for i in range(needle_N):
dial = Qwt.QwtDial(self)
dial_palette = dial.palette()
transparent_color = QtGui.QBrush(QtGui.QColor(255, 255, 255, 0))
dial_palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, transparent_color)
dial_palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, transparent_color)
dial_palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, transparent_color)
dial_palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, transparent_color)
dial_palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, transparent_color)
dial_palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, transparent_color)
dial.setPalette(dial_palette)
dial.setOrigin(180+arc_bias) # Orient dial so 0 is at 9 o'clock
dial.setScaleArc(min_val,max_val)
dial.setRange(min_val, max_val, step)
dial.setScale(min_val, max_val, step)
dial.setScaleTicks(1,20,30)

# Add needle
color_index = int(str(i)[len(str(i))-1:len(str(i)):]) # get last digit of i
if color_index == 0:
needleColor = QtGui.QColor(255, 0, 0) # red
elif color_index == 1:
needleColor = QtGui.QColor(255, 125, 0) # orange
elif color_index == 2:
needleColor = QtGui.QColor(255, 255, 0) # yellow
elif color_index == 3:
needleColor = QtGui.QColor(0, 255, 0) # green
elif color_index == 4:
needleColor = QtGui.QColor(0, 255, 255) # light blue
elif color_index == 5:
needleColor = QtGui.QColor(0, 0, 255) # blue
elif color_index == 6:
needleColor = QtGui.QColor(255, 0, 255) # light purple
elif color_index == 7:
needleColor = QtGui.QColor(150, 0, 255) # purple
elif color_index == 8:
needleColor = QtGui.QColor(150, 100, 0) # brown
else:
needleColor = QtGui.QColor(0, 0, 0) # black
dial.setNeedle(Qwt.QwtDialSimpleNeedle(
Qwt.QwtDialSimpleNeedle.Arrow,
True,
needleColor,
QtGui.QColor(QtCore.Qt.gray).light(130)))
dial.setValue(0)

# Set sizing
dial.setMinimumSize(250,250)
dial.setSizePolicy(Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Expanding)
self.dial_list.append(dial)
self.next_angles.append(0)

# Add to overall layout
self.compass_layout.addWidget(self.dial,0,0)
for i in self.dial_list:
self.compass_layout.addWidget(i,0,0)

# Add label
self.label = Qt.QLabel(label)
Expand All @@ -80,60 +115,26 @@ def __init__(self, label="", min_val=-90, max_val=90, step=10, arc_bias=0, *args
self.this_layout.addWidget(self.label)
self.this_layout.addLayout(self.compass_layout)

# Setup LCD
lcd_layout = Qt.QGridLayout()

self.lcd = QtGui.QLCDNumber(self)
sizePolicy = Qt.QSizePolicy(Qt.QSizePolicy.Preferred, Qt.QSizePolicy.Preferred)
sizePolicy.setHeightForWidth(True)
self.lcd.setSizePolicy(sizePolicy)
self.lcd.setLineWidth(0)

# Set sizing
self.lcd.setMinimumHeight(self.dial.minimumHeight()/2)
self.lcd.setMinimumWidth(self.dial.minimumWidth()/2)

self.lcd.raise_() # Bring to front
self.lcd.setDigitCount(3) # Max digits displayed
self.lcd.setSmallDecimalPoint(True)
self.lcd.display(123.4)
self.compass_layout.addLayout(lcd_layout,0,0)
lcd_layout.addWidget(self.lcd,1,1,1,1)

# Add spacers to center LCD
spacerTop = QtGui.QSpacerItem(1,300,Qt.QSizePolicy.Maximum,Qt.QSizePolicy.Expanding)
spacerSides = QtGui.QSpacerItem(220,1,Qt.QSizePolicy.Maximum,Qt.QSizePolicy.Expanding)
spacerBottom = QtGui.QSpacerItem(1,150,Qt.QSizePolicy.Maximum,Qt.QSizePolicy.Expanding)
# Top Spacers
lcd_layout.addItem(spacerTop,0,1,1,1)
# Side Spacers
lcd_layout.addItem(spacerSides,1,0,1,1)
lcd_layout.addItem(spacerSides,1,2,1,1)
# Bottom Spacers
lcd_layout.addItem(spacerBottom,2,1,1,1)

self.label.raise_()

# connect the plot callback signal
QtCore.QObject.connect(self,
QtCore.SIGNAL("updatePlot(int)"),
self.do_plot)

def change_angle(self,angle):
self.dial.setValue(float(angle))

def trigger_update(self):
self.emit(QtCore.SIGNAL("updatePlot(int)"), 0)

def do_plot(self, a):
# Update qt plots
self.change_angle(self.next_angle)
self.lcd.display(self.next_angle)
self.replot()
for i in range(len(self.dial_list)):
self.dial_list[i].setValue(self.next_angles[i])
self.replot()

def work(self, input_items, output_items):
# Average inputs
self.next_angle = numpy.mean(input_items[0])
for i in range(len(self.next_angles)):
self.next_angles[i] = numpy.mean(input_items[i])

if (time.time() - self.last)>self.update_period:
self.last = time.time()
Expand Down