Skip to content
Snippets Groups Projects
Commit c93da372 authored by Jeffrey Fisher's avatar Jeffrey Fisher
Browse files

WIP Control 8 thruster PWMs with global stop

Right now it is just the UI, it is not hooked up to ROS.
parent ab8d72c0
No related branches found
No related tags found
No related merge requests found
# Setup
(1) Clone into your ROS workspace, for example:
```
cd ~/ros_ws/src
git clone git@code.umd.edu:robotics-at-maryland/qubo_gui.git
```
(2) Build your ROS workspace:
```
cd ~/ros_ws
colcon build
```
(3) For now, run `rqt` from the commandline. Then load the plugins you want inside the rqt GUI.
- Click "Plugins" in the menu bar.
- Find the plugin you want.
## Building and running the code
```
colcon build
```
# Development
## Adding or modifying a plugin
- Update `plugin.xml`
- You need one `<class>` tag per plugin.
- Make sure `type=` attribute has the correct Python import path to refer to your plugin class.
Suggested naming convention: Organize under a "Qubo" group, so that it is easy to find our custom plugins in rqt. For example:
```xml
...
<class ...>
...
<qtgui>
<group>
<label>Qubo Control</label>
</group>
<label>Thruster Control</label>
...
</qtgui>
</class>
```
\ No newline at end of file
<library path="qubo_gui">
<class name="ThrustersPlugin" type="qubo_gui.thrusters.Thrusters" base_class_type="rqt_gui_py::Plugin">
<class name="ThrustersPlugin" type="qubo_gui.thruster_control.ThrusterControl" base_class_type="rqt_gui_py::Plugin">
<description>
An example Python GUI plugin to create a great user interface.
</description>
<qtgui>
<group>
<label>Visualization</label>
<label>Qubo Control</label>
</group>
<label>My first Python Plugin</label>
<label>Qubo Thruster Control</label>
<icon type="theme">system-help</icon>
<statustip>Great user interface to provide real value.</statustip>
</qtgui>
</class>
<class name="ExamplePlugin" type="qubo_gui.plugin2.Plugin2" base_class_type="rqt_gui_py::Plugin">
<description>
An example Python GUI plugin to create a great user interface.
......
from .thrusters import Thrusters
from .thruster_control import Thrusters
def main():
print('Hi from qubo_gui.')
......
"""
This file implements an rqt plugin for controlling individual thrusters on Qubo.
Set
"""
import random
from qt_gui.plugin import Plugin
from python_qt_binding import QtCore
from python_qt_binding.QtCore import Qt
from python_qt_binding.QtWidgets import QWidget, QLabel, QSlider, QPushButton, QHBoxLayout, QVBoxLayout
# https://stackoverflow.com/questions/77934193/how-can-i-create-a-simple-gui-using-an-rqt-plugin
class ThrusterControl(Plugin):
def __init__(self, context):
super(ThrusterControl, self).__init__(context)
self._context = context
self.setObjectName("ThrustersPlugin")
self._widget = QWidget()
front_widget = QWidget()
front = QHBoxLayout(front_widget)
front_left = ThrusterWidget("Front Left", top_topic="/thruster1", bottom_topic="/thruster2")
front_right = ThrusterWidget("Front Right", "", "")
front.addWidget(front_left)
front.addWidget(front_right)
back_widget = QWidget()
back = QHBoxLayout(back_widget)
back_left = ThrusterWidget("Back Left", "", "")
back_right = ThrusterWidget("Back Right", "", "")
back.addWidget(back_left)
back.addWidget(back_right)
self._stop_button = QPushButton("Global Stop")
# When _stop_button's "clicked" signal is emitted, all thruster control widgets
# will have their stop_top and stop_bottom slots triggered.
for w in [front_left, front_right, back_left, back_right]:
self._stop_button.clicked.connect(w.stop_top)
self._stop_button.clicked.connect(w.stop_bottom)
layout = QVBoxLayout(self._widget)
layout.addWidget(self._stop_button)
layout.addWidget(front_widget)
layout.addWidget(back_widget)
context.add_widget(self._widget)
# Widget to control two thrusters (top and bottom one).
class ThrusterWidget(QWidget):
PWM_STOP = 1500
def __init__(self, title, top_topic, bottom_topic):
super().__init__()
self._top_topic = top_topic
self._bottom_topic = bottom_topic
title_label = QLabel(title)
self.top_stop_btn = QPushButton("Stop")
self.top_pwm_label = QLabel()
self.top_slider = QSlider(Qt.Horizontal)
self.bottom_slider = QSlider(Qt.Horizontal)
self.bottom_stop_btn = QPushButton("Stop")
self.bottom_pwm_label = QLabel()
top_widget = QWidget()
top_layout = QHBoxLayout(top_widget)
top_layout.addWidget(self.top_stop_btn)
top_layout.addWidget(self.top_pwm_label)
bottom_widget = QWidget()
bottom_layout = QHBoxLayout(bottom_widget)
bottom_layout.addWidget(self.bottom_stop_btn)
bottom_layout.addWidget(self.bottom_pwm_label)
self.layout = QVBoxLayout(self)
self.layout.addWidget(top_widget)
self.layout.addWidget(self.top_slider)
self.layout.addWidget(self.bottom_slider)
self.layout.addWidget(bottom_widget)
self.top_slider.setTickPosition(QSlider.TicksBothSides)
self.top_slider.setTickInterval(20)
self.top_slider.setMinimum(1400)
self.top_slider.setMaximum(1600)
self.top_slider.setValue(1500)
self.top_pwm_label.setText(f"PWM: {1500}")
self.top_slider.valueChanged.connect(self.on_top_value_changed)
self.bottom_slider.setTickPosition(QSlider.TicksBothSides)
self.bottom_slider.setTickInterval(20)
self.bottom_slider.setMinimum(1400)
self.bottom_slider.setMaximum(1600)
self.bottom_slider.setValue(1500)
self.bottom_pwm_label.setText(f"PWM: {1500}")
self.bottom_slider.valueChanged.connect(self.on_bottom_value_changed)
self.top_stop_btn.clicked.connect(self.stop_top)
self.bottom_stop_btn.clicked.connect(self.stop_bottom)
@QtCore.Slot(int)
def on_top_value_changed(self, value):
self.top_pwm_label.setText(f"PWM: {value}")
# TODO: Publish on ROS to set actual PWM. Make sure we have a controller to prevent PWM from changing too rapidly.
@QtCore.Slot(int)
def on_bottom_value_changed(self, value):
self.bottom_pwm_label.setText(f"PWM: {value}")
# TODO: Publish on ROS to set actual PWM.
@QtCore.Slot()
def stop_top(self):
self.top_slider.setValue(self.PWM_STOP)
@QtCore.Slot()
def stop_bottom(self):
self.bottom_slider.setValue(self.PWM_STOP)
\ No newline at end of file
import random
from qt_gui.plugin import Plugin
from python_qt_binding import QtCore
# from python_qt_binding.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel
import python_qt_binding.QtWidgets as QtWidgets
# https://stackoverflow.com/questions/77934193/how-can-i-create-a-simple-gui-using-an-rqt-plugin
class Thrusters(Plugin):
def __init__(self, context):
super(Thrusters, self).__init__(context)
self._context = context
self.setObjectName("ThrustersPlugin")
self._widget = MyWidget()
self._widget.show()
context.add_widget(self._widget)
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.hello = ["Hallo Welt", "Hei maailma", "Hola Mundo", "Привет мир"]
self.button = QtWidgets.QPushButton("Click me!")
self.text = QtWidgets.QLabel("Hello World",
alignment=QtCore.Qt.AlignCenter)
self.layout = QtWidgets.QVBoxLayout(self)
self.layout.addWidget(self.text)
self.layout.addWidget(self.button)
self.button.clicked.connect(self.magic)
@QtCore.Slot()
def magic(self):
self.text.setText(random.choice(self.hello))
# class MyWidget(QWidget):
# def __init__(self):
# super(MyWidget, self).__init__()
# print("MyWidget constructor called...")
# self.setStyleSheet("background-color: white;")
# # Create a layout
# layout = QVBoxLayout(self)
# # Create a button
# self.button = QPushButton('Click Me!', self)
# self.button.clicked.connect(self.on_button_click)
# # Create a label for text display
# self.label = QLabel('Hello, World!', self)
# # Add the button and label to the layout
# layout.addWidget(self.button)
# layout.addWidget(self.label)
# # Set the layout for the widget
# self.setLayout(layout)
# def on_button_click(self):
# self.label.setText('Button Clicked!')
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment