ARTICLE AD BOX
I'm working on a project that uses an X440 radio from Ettus Research, which relies on UHD under the hood for its API. My application has three main components:
C++ files that handle all of the UHD/USRP calls and the high-speed interfaces between the radio and the stream endpoints.
A Python script that uses NiceGUI to send commands to the C++ application to control the behavior of the USRP.
A Python script that uses PyQt to display a basic spectrum analyzer view of a portion of the samples received from the radio. These samples are streamed over ZMQ at a low enough rate to avoid overflow.
All of these scripts are running on a headless RHEL9 machine, which I access via SSH.
I'm experiencing an issue between parts 1 and 3 when I try to use the C++ files with the spectrum analyzer GUI.
If I start the spectrum analyzer Python script before calling the uhd::usrp::multi_usrp::make() function in my C++ application, the spectrum analyzer works as expected. The X-forwarded window pops up, and I can interact with it normally. Additioanlly, the spectrum analyzer continues to work after I run uhd::usrp::multi_usrp::make().
However, if I run the spectrum analyzer Python script after calling uhd::usrp::multi_usrp::make(), the GUI goes through the setup steps but never displays. Furthermore, I can't stop the script with CTRL-C in the console. The only way to get the script to respond is to kill the C++ application. Once the C++ application is killed, the spectrum analyzer GUI pops up correctly.
Because of the high data rate from the X440, UHD is using DPDK under the hood. I am not sure if that's relevant, but I wanted to mention it.
What could be causing this? I've tried debugging on the Python side, but I suspect it's getting hung at the system level, so Python debugging hasn't been effective.
Minimal GUI Code that reproduces the issue:
from pyqtgraph.Qt import QtWidgets, QtCore class myGui(QtWidgets.QWidget): def __init__(self): super().__init__() # Layout layout = QtWidgets.QVBoxLayout(self) ctrl_layout = QtWidgets.QHBoxLayout() layout.addLayout(ctrl_layout) print("Done here") # This line prints but then the app never shows if # started after the C++ applications def main(): print("main") app = QtWidgets.QApplication([]) gui = myGui() gui.resize(1200, 900) gui.show() app.exec() if __name__ == "__main__": main()Minimal C++ code that will cause the hang if the GUI code is started after the USRP is made:
#include <uhd/convert.hpp> #include <uhd/usrp/multi_usrp.hpp> #include <uhd/utils/safe_main.hpp> #include <uhd/utils/thread.hpp> #include <boost/algorithm/string.hpp> #include <iostream> #include <chrono> #include <thread> int UHD_SAFE_MAIN(int argc, char* argv[]) { // minimal config for demonstration uhd::usrp::multi_usrp::sptr usrp_; std::cout << "Before usrp, waiting 20 seconds" << std::endl; //GUI wont hang here std::this_thread::sleep_for(std::chrono::seconds(20)); std::cout << "Making USRP" << std::endl; usrp_ = uhd::usrp::multi_usrp::make("addr=192.168.10.2, second_addr=192.168.20.2," "mgmt_addr=192.168.200.2,use_dpdk=1, master_clock_rate=500e6," "converter_clock_rate=4e9"); std::cout << "Finished making USRP, waiting 20 seconds" << std::endl; //GUI now hangs std::this_thread::sleep_for(std::chrono::seconds(20)); return 0; }