From 332d50e03cc8aa90b2836a6c32ec0f4c1c0f6794 Mon Sep 17 00:00:00 2001 From: jmacuga Date: Tue, 9 May 2023 18:24:55 +0200 Subject: [PATCH 1/3] moteus plugin package created --- .gitignore | 5 + src/moteus_plugin/moteus_plugin/__init__.py | 0 .../moteus_plugin/moteus_plugin.py | 20 + .../moteus_plugin/moteus_plugin.ui | 487 ++++++++++++++++++ .../moteus_plugin/ui_moteus_plugin.py | 430 ++++++++++++++++ src/moteus_plugin/package.xml | 21 + src/moteus_plugin/resource/moteus_plugin | 0 src/moteus_plugin/setup.cfg | 4 + src/moteus_plugin/setup.py | 26 + src/moteus_plugin/test/test_copyright.py | 25 + src/moteus_plugin/test/test_flake8.py | 25 + src/moteus_plugin/test/test_pep257.py | 23 + 12 files changed, 1066 insertions(+) create mode 100644 src/moteus_plugin/moteus_plugin/__init__.py create mode 100644 src/moteus_plugin/moteus_plugin/moteus_plugin.py create mode 100644 src/moteus_plugin/moteus_plugin/moteus_plugin.ui create mode 100644 src/moteus_plugin/moteus_plugin/ui_moteus_plugin.py create mode 100644 src/moteus_plugin/package.xml create mode 100644 src/moteus_plugin/resource/moteus_plugin create mode 100644 src/moteus_plugin/setup.cfg create mode 100644 src/moteus_plugin/setup.py create mode 100644 src/moteus_plugin/test/test_copyright.py create mode 100644 src/moteus_plugin/test/test_flake8.py create mode 100644 src/moteus_plugin/test/test_pep257.py diff --git a/.gitignore b/.gitignore index 35d74bb7..8efa61da 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ logs/ build/ bin/ lib/ +log/ msg_gen/ srv_gen/ msg/*Action.msg @@ -49,3 +50,7 @@ qtcreator-* # Catkin custom files CATKIN_IGNORE + + +#vscode +.vscode/ \ No newline at end of file diff --git a/src/moteus_plugin/moteus_plugin/__init__.py b/src/moteus_plugin/moteus_plugin/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/moteus_plugin/moteus_plugin/moteus_plugin.py b/src/moteus_plugin/moteus_plugin/moteus_plugin.py new file mode 100644 index 00000000..96ca256f --- /dev/null +++ b/src/moteus_plugin/moteus_plugin/moteus_plugin.py @@ -0,0 +1,20 @@ +import sys +from PySide6.QtWidgets import QApplication, QMainWindow, QWidget +from PySide6.QtCore import QFile +from ui_moteus_plugin import Ui_Form + + +class Form(QWidget): + def __init__(self): + super(Form, self).__init__() + self.ui = Ui_Form() + self.ui.setupUi(self) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + window = Form() + window.show() + + sys.exit(app.exec()) diff --git a/src/moteus_plugin/moteus_plugin/moteus_plugin.ui b/src/moteus_plugin/moteus_plugin/moteus_plugin.ui new file mode 100644 index 00000000..a0418a9f --- /dev/null +++ b/src/moteus_plugin/moteus_plugin/moteus_plugin.ui @@ -0,0 +1,487 @@ + + + Form + + + + 0 + 0 + 612 + 617 + + + + Form + + + QWidget { + background-color: #ffffff; + color: #333333; + border: 1px solid #bbbbbb; + border-radius: 5px; + font-family: Arial; + font-size: 12pt; +} + +QPushButton { + background-color: #008cff; + color: #ffffff; + border: none; + border-radius: 5px; + padding: 5px 10px; + font-family: Arial; + font-size: 12pt; +} + +QPushButton:hover { + background-color: #0066cc; +} + +QLineEdit { + background-color: #ffffff; + color: #333333; + border: 1px solid #bbbbbb; + border-radius: 5px; + font-family: Arial; + font-size: 12pt; +} + + + + + + + + + 0 + 0 + + + + QLabel { + font-size: 30px; + font-weight: bold; + color: #333333; + background-color: rgb(153, 193, 241); + padding: 4px; + border-bottom: 2px solid #cccccc; +} + + + + Moteus UI + + + + + + + + + + 0 + 0 + + + + QLabel { + color: #555; + font-size: 16px; + font-weight: bold; + border: none; +} + + + Choose Moteus: + + + + + + + + 0 + 0 + + + + QComboBox { + border: 1px solid gray; + border-radius: 5px; + padding: 1px 18px 1px 3px; + min-width: 6em; + font-size: 14px; + font-weight: bold; + color: #333333; + background-color: white; + selection-background-color: #DA2E2E; +} + +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 20px; + border-left-width: 1px; + border-left-color: gray; + border-left-style: solid; + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; +} + +QComboBox::hover { + border: 1px solid #DA2E2E; +} + +QComboBox::pressed { + border: 1px solid #DA2E2E; + background-color: #DA2E2E; + color: white; +} + + + + + + + + + + + 4 + + + Qt::Horizontal + + + + + + + + + + + + Arial + -1 + 75 + true + + + + QLabel { + font-size: 25px; + font-weight: bold; + color: #333333; + background-color: #f2f2f2; + padding: 4px; + border-bottom: 2px solid #cccccc; +} + + + + Moteus Control + + + + + + + QLabel { + color: #555; + font-size: 16px; + font-weight: bold; + border: none; +} + + + position + + + + + + + QDoubleSpinBox { + border: 1px solid #d9d9d9; + border-radius: 3px; + padding: 3px; + font-size: 14px; + font-family: Arial; + color: #4d4d4d; +} + + + + + + + + QLabel { + color: #555; + font-size: 16px; + font-weight: bold; + border: none; +} + + + velocity + + + + + + + QDoubleSpinBox { + border: 1px solid #d9d9d9; + border-radius: 3px; + padding: 3px; + font-size: 14px; + font-family: Arial; + color: #4d4d4d; +} + + + + + + + QLabel { + color: #555; + font-size: 16px; + font-weight: bold; + border: none; +} + + + torque + + + + + + + QDoubleSpinBox { + border: 1px solid #d9d9d9; + border-radius: 3px; + padding: 3px; + font-size: 14px; + font-family: Arial; + color: #4d4d4d; +} + + + + + + + + + + 128 + 50 + + + + + Arial + -1 + 75 + false + true + + + + QPushButton{ + background-color: rgb(53, 132, 228); + border-style: outset; + border-width: 2px; + border-radius: 10px; + border-color: beige; + font: bold 25px; + color: white; + min-width: 4em; + padding: 4px; +} + + + SET + + + + 19 + 100 + + + + + + + + + + + + QLabel { + font-size: 25px; + font-weight: bold; + color: #333333; + background-color: #f2f2f2; + padding: 4px; + border-bottom: 2px solid #cccccc; +} + + + + Moteus State + + + + + + + QLabel { + color: #555; + font-size: 16px; + font-weight: bold; + border: none; +} + + + current position + + + + + + + QLCDNumber { + background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #434343, stop:1 #2b2b2b); + color: #b3b3b3; + border-radius: 10px; + padding: 5px; + border: none; +} +QLCDNumber::number { + background-color: none; +} + + + + + + + QLabel { + color: #555; + font-size: 16px; + font-weight: bold; + border: none; +} + + + current velocity + + + + + + + QLCDNumber { + background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #434343, stop:1 #2b2b2b); + color: #b3b3b3; + border-radius: 10px; + padding: 5px; + border: none; +} +QLCDNumber::number { + background-color: none; +} + + + + + + + QLabel { + color: #555; + font-size: 16px; + font-weight: bold; + border: none; +} + + + + current torque + + + + + + + QLCDNumber { + background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #434343, stop:1 #2b2b2b); + color: #b3b3b3; + border-radius: 10px; + padding: 5px; + border: none; +} +QLCDNumber::number { + background-color: none; +} + + + + + + + + + 132 + 50 + + + + + Arial + -1 + 75 + false + true + + + + QPushButton{ + background-color: rgb(224, 27, 36); + border-style: outset; + border-width: 2px; + border-radius: 10px; + border-color: beige; + font: bold 25px; + color: white; + min-width: 4em; + padding: 6px; +} + + + STOP + + + + 16 + 100 + + + + 100 + + + + + + + + + + + + diff --git a/src/moteus_plugin/moteus_plugin/ui_moteus_plugin.py b/src/moteus_plugin/moteus_plugin/ui_moteus_plugin.py new file mode 100644 index 00000000..c4e6322b --- /dev/null +++ b/src/moteus_plugin/moteus_plugin/ui_moteus_plugin.py @@ -0,0 +1,430 @@ +# -*- coding: utf-8 -*- + +################################################################################ +# Form generated from reading UI file 'moteus_plugin.ui' +## +# Created by: Qt User Interface Compiler version 6.5.0 +## +# WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QComboBox, QDoubleSpinBox, QFrame, + QHBoxLayout, QLCDNumber, QLabel, QPushButton, + QSizePolicy, QVBoxLayout, QWidget) + + +class Ui_Form(object): + def setupUi(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + Form.resize(612, 617) + Form.setStyleSheet(u"QWidget {\n" + " background-color: #ffffff;\n" + " color: #333333;\n" + " border: 1px solid #bbbbbb;\n" + " border-radius: 5px;\n" + " font-family: Arial;\n" + " font-size: 12pt;\n" + "}\n" + "\n" + "QPushButton {\n" + " background-color: #008cff;\n" + " color: #ffffff;\n" + " border: none;\n" + " border-radius: 5px;\n" + " padding: 5px 10px;\n" + " font-family: Arial;\n" + " font-size: 12pt;\n" + "}\n" + "\n" + "QPushButton:hover {\n" + " background-color: #0066cc;\n" + "}\n" + "\n" + "QLineEdit {\n" + " background-color: #ffffff;\n" + " color: #333333;\n" + " border: 1px solid #bbbbbb;\n" + " border-radius: 5px;\n" + " font-family: Arial;\n" + " font-size: 12pt;\n" + "}") + self.verticalLayout_4 = QVBoxLayout(Form) + self.verticalLayout_4.setObjectName(u"verticalLayout_4") + self.verticalLayout = QVBoxLayout() + self.verticalLayout.setObjectName(u"verticalLayout") + self.label_10 = QLabel(Form) + self.label_10.setObjectName(u"label_10") + sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth( + self.label_10.sizePolicy().hasHeightForWidth()) + self.label_10.setSizePolicy(sizePolicy) + self.label_10.setStyleSheet(u"QLabel {\n" + " font-size: 30px;\n" + " font-weight: bold;\n" + " color: #333333;\n" + " background-color: rgb(153, 193, 241);\n" + " padding: 4px;\n" + " border-bottom: 2px solid #cccccc;\n" + "}\n" + "") + + self.verticalLayout.addWidget(self.label_10) + + self.horizontalLayout_3 = QHBoxLayout() + self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") + self.label_8 = QLabel(Form) + self.label_8.setObjectName(u"label_8") + sizePolicy1 = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth( + self.label_8.sizePolicy().hasHeightForWidth()) + self.label_8.setSizePolicy(sizePolicy1) + self.label_8.setStyleSheet(u"QLabel {\n" + " color: #555;\n" + " font-size: 16px;\n" + " font-weight: bold;\n" + " border: none;\n" + "}") + + self.horizontalLayout_3.addWidget(self.label_8) + + self.comboBox = QComboBox(Form) + self.comboBox.setObjectName(u"comboBox") + sizePolicy2 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth( + self.comboBox.sizePolicy().hasHeightForWidth()) + self.comboBox.setSizePolicy(sizePolicy2) + self.comboBox.setStyleSheet(u"QComboBox {\n" + " border: 1px solid gray;\n" + " border-radius: 5px;\n" + " padding: 1px 18px 1px 3px;\n" + " min-width: 6em;\n" + " font-size: 14px;\n" + " font-weight: bold;\n" + " color: #333333;\n" + " background-color: white;\n" + " selection-background-color: #DA2E2E;\n" + "}\n" + "\n" + "QComboBox::drop-down {\n" + " subcontrol-origin: padding;\n" + " subcontrol-position: top right;\n" + " width: 20px;\n" + " border-left-width: 1px;\n" + " border-left-color: gray;\n" + " border-left-style: solid;\n" + " border-top-right-radius: 5px;\n" + " border-bottom-right-radius: 5px;\n" + "}\n" + "\n" + "QComboBox::hover {\n" + " border: 1px solid #DA2E2E;\n" + "}\n" + "\n" + "QComboBox::pressed {\n" + " border: 1px solid #DA2E2E;\n" + " background-color: #DA2E2E;\n" + " color: white;\n" + "}") + + self.horizontalLayout_3.addWidget(self.comboBox) + + self.verticalLayout.addLayout(self.horizontalLayout_3) + + self.verticalLayout_4.addLayout(self.verticalLayout) + + self.line = QFrame(Form) + self.line.setObjectName(u"line") + self.line.setLineWidth(4) + self.line.setFrameShape(QFrame.HLine) + self.line.setFrameShadow(QFrame.Sunken) + + self.verticalLayout_4.addWidget(self.line) + + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.verticalLayout_2 = QVBoxLayout() + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.label = QLabel(Form) + self.label.setObjectName(u"label") + font = QFont() + font.setFamilies([u"Arial"]) + font.setBold(True) + self.label.setFont(font) + self.label.setStyleSheet(u"QLabel {\n" + " font-size: 25px;\n" + " font-weight: bold;\n" + " color: #333333;\n" + " background-color: #f2f2f2;\n" + " padding: 4px;\n" + " border-bottom: 2px solid #cccccc;\n" + "}\n" + "") + + self.verticalLayout_2.addWidget(self.label) + + self.label_2 = QLabel(Form) + self.label_2.setObjectName(u"label_2") + self.label_2.setStyleSheet(u"QLabel {\n" + " color: #555;\n" + " font-size: 16px;\n" + " font-weight: bold;\n" + " border: none;\n" + "}") + + self.verticalLayout_2.addWidget(self.label_2) + + self.doubleSpinBox_3 = QDoubleSpinBox(Form) + self.doubleSpinBox_3.setObjectName(u"doubleSpinBox_3") + self.doubleSpinBox_3.setStyleSheet(u"QDoubleSpinBox {\n" + " border: 1px solid #d9d9d9;\n" + " border-radius: 3px;\n" + " padding: 3px;\n" + " font-size: 14px;\n" + " font-family: Arial;\n" + " color: #4d4d4d;\n" + "}\n" + "") + + self.verticalLayout_2.addWidget(self.doubleSpinBox_3) + + self.label_3 = QLabel(Form) + self.label_3.setObjectName(u"label_3") + self.label_3.setStyleSheet(u"QLabel {\n" + " color: #555;\n" + " font-size: 16px;\n" + " font-weight: bold;\n" + " border: none;\n" + "}") + + self.verticalLayout_2.addWidget(self.label_3) + + self.doubleSpinBox_2 = QDoubleSpinBox(Form) + self.doubleSpinBox_2.setObjectName(u"doubleSpinBox_2") + self.doubleSpinBox_2.setStyleSheet(u"QDoubleSpinBox {\n" + " border: 1px solid #d9d9d9;\n" + " border-radius: 3px;\n" + " padding: 3px;\n" + " font-size: 14px;\n" + " font-family: Arial;\n" + " color: #4d4d4d;\n" + "}") + + self.verticalLayout_2.addWidget(self.doubleSpinBox_2) + + self.label_4 = QLabel(Form) + self.label_4.setObjectName(u"label_4") + self.label_4.setStyleSheet(u"QLabel {\n" + " color: #555;\n" + " font-size: 16px;\n" + " font-weight: bold;\n" + " border: none;\n" + "}") + + self.verticalLayout_2.addWidget(self.label_4) + + self.doubleSpinBox = QDoubleSpinBox(Form) + self.doubleSpinBox.setObjectName(u"doubleSpinBox") + self.doubleSpinBox.setStyleSheet(u"QDoubleSpinBox {\n" + " border: 1px solid #d9d9d9;\n" + " border-radius: 3px;\n" + " padding: 3px;\n" + " font-size: 14px;\n" + " font-family: Arial;\n" + " color: #4d4d4d;\n" + "}\n" + "\n" + "") + + self.verticalLayout_2.addWidget(self.doubleSpinBox) + + self.pushButton = QPushButton(Form) + self.pushButton.setObjectName(u"pushButton") + self.pushButton.setMinimumSize(QSize(128, 50)) + font1 = QFont() + font1.setFamilies([u"Arial"]) + font1.setBold(True) + font1.setItalic(False) + self.pushButton.setFont(font1) + self.pushButton.setStyleSheet(u"QPushButton{\n" + " background-color: rgb(53, 132, 228);\n" + " border-style: outset;\n" + " border-width: 2px;\n" + " border-radius: 10px;\n" + " border-color: beige;\n" + " font: bold 25px;\n" + " color: white;\n" + " min-width: 4em;\n" + " padding: 4px;\n" + "}") + self.pushButton.setIconSize(QSize(19, 100)) + + self.verticalLayout_2.addWidget(self.pushButton) + + self.horizontalLayout.addLayout(self.verticalLayout_2) + + self.verticalLayout_3 = QVBoxLayout() + self.verticalLayout_3.setObjectName(u"verticalLayout_3") + self.label_5 = QLabel(Form) + self.label_5.setObjectName(u"label_5") + self.label_5.setStyleSheet(u"QLabel {\n" + " font-size: 25px;\n" + " font-weight: bold;\n" + " color: #333333;\n" + " background-color: #f2f2f2;\n" + " padding: 4px;\n" + " border-bottom: 2px solid #cccccc;\n" + "}\n" + "") + + self.verticalLayout_3.addWidget(self.label_5) + + self.label_6 = QLabel(Form) + self.label_6.setObjectName(u"label_6") + self.label_6.setStyleSheet(u"QLabel {\n" + " color: #555;\n" + " font-size: 16px;\n" + " font-weight: bold;\n" + " border: none;\n" + "}") + + self.verticalLayout_3.addWidget(self.label_6) + + self.lcdNumber_2 = QLCDNumber(Form) + self.lcdNumber_2.setObjectName(u"lcdNumber_2") + self.lcdNumber_2.setStyleSheet(u"QLCDNumber {\n" + " background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #434343, stop:1 #2b2b2b);\n" + " color: #b3b3b3;\n" + " border-radius: 10px;\n" + " padding: 5px;\n" + " border: none;\n" + "}\n" + "QLCDNumber::number {\n" + " background-color: none;\n" + "}") + + self.verticalLayout_3.addWidget(self.lcdNumber_2) + + self.label_7 = QLabel(Form) + self.label_7.setObjectName(u"label_7") + self.label_7.setStyleSheet(u"QLabel {\n" + " color: #555;\n" + " font-size: 16px;\n" + " font-weight: bold;\n" + " border: none;\n" + "}") + + self.verticalLayout_3.addWidget(self.label_7) + + self.lcdNumber = QLCDNumber(Form) + self.lcdNumber.setObjectName(u"lcdNumber") + self.lcdNumber.setStyleSheet(u"QLCDNumber {\n" + " background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #434343, stop:1 #2b2b2b);\n" + " color: #b3b3b3;\n" + " border-radius: 10px;\n" + " padding: 5px;\n" + " border: none;\n" + "}\n" + "QLCDNumber::number {\n" + " background-color: none;\n" + "}") + + self.verticalLayout_3.addWidget(self.lcdNumber) + + self.label_9 = QLabel(Form) + self.label_9.setObjectName(u"label_9") + self.label_9.setStyleSheet(u"QLabel {\n" + " color: #555;\n" + " font-size: 16px;\n" + " font-weight: bold;\n" + " border: none;\n" + "}\n" + "") + + self.verticalLayout_3.addWidget(self.label_9) + + self.lcdNumber_3 = QLCDNumber(Form) + self.lcdNumber_3.setObjectName(u"lcdNumber_3") + self.lcdNumber_3.setStyleSheet(u"QLCDNumber {\n" + " background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #434343, stop:1 #2b2b2b);\n" + " color: #b3b3b3;\n" + " border-radius: 10px;\n" + " padding: 5px;\n" + " border: none;\n" + "}\n" + "QLCDNumber::number {\n" + " background-color: none;\n" + "}\n" + "") + + self.verticalLayout_3.addWidget(self.lcdNumber_3) + + self.pushButton_2 = QPushButton(Form) + self.pushButton_2.setObjectName(u"pushButton_2") + self.pushButton_2.setMinimumSize(QSize(132, 50)) + self.pushButton_2.setFont(font1) + self.pushButton_2.setStyleSheet(u"QPushButton{\n" + " background-color: rgb(224, 27, 36);\n" + " border-style: outset;\n" + " border-width: 2px;\n" + " border-radius: 10px;\n" + " border-color: beige;\n" + " font: bold 25px;\n" + " color: white;\n" + " min-width: 4em;\n" + " padding: 6px;\n" + "}") + self.pushButton_2.setIconSize(QSize(16, 100)) + self.pushButton_2.setAutoRepeatInterval(100) + + self.verticalLayout_3.addWidget(self.pushButton_2) + + self.horizontalLayout.addLayout(self.verticalLayout_3) + + self.verticalLayout_4.addLayout(self.horizontalLayout) + + self.retranslateUi(Form) + + QMetaObject.connectSlotsByName(Form) + # setupUi + + def retranslateUi(self, Form): + Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None)) + self.label_10.setText( + QCoreApplication.translate("Form", u"Moteus UI", None)) + self.label_8.setText(QCoreApplication.translate( + "Form", u"Choose Moteus:", None)) + self.label.setText(QCoreApplication.translate( + "Form", u"Moteus Control", None)) + self.label_2.setText( + QCoreApplication.translate("Form", u"position", None)) + self.label_3.setText( + QCoreApplication.translate("Form", u"velocity", None)) + self.label_4.setText( + QCoreApplication.translate("Form", u"torque", None)) + self.pushButton.setText( + QCoreApplication.translate("Form", u"SET", None)) + self.label_5.setText(QCoreApplication.translate( + "Form", u"Moteus State", None)) + self.label_6.setText(QCoreApplication.translate( + "Form", u"current position", None)) + self.label_7.setText(QCoreApplication.translate( + "Form", u"current velocity", None)) + self.label_9.setText(QCoreApplication.translate( + "Form", u"current torque", None)) + self.pushButton_2.setText( + QCoreApplication.translate("Form", u"STOP", None)) + # retranslateUi diff --git a/src/moteus_plugin/package.xml b/src/moteus_plugin/package.xml new file mode 100644 index 00000000..aee2a1f0 --- /dev/null +++ b/src/moteus_plugin/package.xml @@ -0,0 +1,21 @@ + + + + moteus_plugin + 0.0.0 + TODO: Package description + jmacuga + TODO: License declaration + + rqt_gui_py + + ament_copyright + ament_flake8 + ament_pep257 + python3-pytest + + + ament_python + + diff --git a/src/moteus_plugin/resource/moteus_plugin b/src/moteus_plugin/resource/moteus_plugin new file mode 100644 index 00000000..e69de29b diff --git a/src/moteus_plugin/setup.cfg b/src/moteus_plugin/setup.cfg new file mode 100644 index 00000000..5ddf32c3 --- /dev/null +++ b/src/moteus_plugin/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/moteus_plugin +[install] +install_scripts=$base/lib/moteus_plugin diff --git a/src/moteus_plugin/setup.py b/src/moteus_plugin/setup.py new file mode 100644 index 00000000..905acc92 --- /dev/null +++ b/src/moteus_plugin/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup + +package_name = 'moteus_plugin' + +setup( + name=package_name, + version='0.0.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', + ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='jmacuga', + maintainer_email='julia.macuga +@gmail.com', + description='TODO: Package description', + license='TODO: License declaration', + tests_require=['pytest'], + entry_points={ + 'console_scripts': [ + ], + }, +) diff --git a/src/moteus_plugin/test/test_copyright.py b/src/moteus_plugin/test/test_copyright.py new file mode 100644 index 00000000..97a39196 --- /dev/null +++ b/src/moteus_plugin/test/test_copyright.py @@ -0,0 +1,25 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_copyright.main import main +import pytest + + +# Remove the `skip` decorator once the source file(s) have a copyright header +@pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') +@pytest.mark.copyright +@pytest.mark.linter +def test_copyright(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found errors' diff --git a/src/moteus_plugin/test/test_flake8.py b/src/moteus_plugin/test/test_flake8.py new file mode 100644 index 00000000..27ee1078 --- /dev/null +++ b/src/moteus_plugin/test/test_flake8.py @@ -0,0 +1,25 @@ +# Copyright 2017 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_flake8.main import main_with_errors +import pytest + + +@pytest.mark.flake8 +@pytest.mark.linter +def test_flake8(): + rc, errors = main_with_errors(argv=[]) + assert rc == 0, \ + 'Found %d code style errors / warnings:\n' % len(errors) + \ + '\n'.join(errors) diff --git a/src/moteus_plugin/test/test_pep257.py b/src/moteus_plugin/test/test_pep257.py new file mode 100644 index 00000000..b234a384 --- /dev/null +++ b/src/moteus_plugin/test/test_pep257.py @@ -0,0 +1,23 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_pep257.main import main +import pytest + + +@pytest.mark.linter +@pytest.mark.pep257 +def test_pep257(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found code style errors / warnings' From e75c158ea7b3d69474b346c1c23762f3c7e7da0a Mon Sep 17 00:00:00 2001 From: jmacuga Date: Tue, 9 May 2023 20:06:38 +0200 Subject: [PATCH 2/3] plugin.xml created --- .gitignore | 1 + src/meldog_bridge/setup.py | 2 + .../moteus_plugin/moteus_plugin.py | 76 +++++++++++++++---- src/moteus_plugin/package.xml | 7 +- src/moteus_plugin/plugin.xml | 20 +++++ src/moteus_plugin/setup.py | 8 +- 6 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 src/moteus_plugin/plugin.xml diff --git a/.gitignore b/.gitignore index 8efa61da..ac0357f3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build/ bin/ lib/ log/ +install/ msg_gen/ srv_gen/ msg/*Action.msg diff --git a/src/meldog_bridge/setup.py b/src/meldog_bridge/setup.py index be444dd5..696e9888 100644 --- a/src/meldog_bridge/setup.py +++ b/src/meldog_bridge/setup.py @@ -1,4 +1,6 @@ +import os from setuptools import setup +from glob import glob package_name = 'meldog_bridge' diff --git a/src/moteus_plugin/moteus_plugin/moteus_plugin.py b/src/moteus_plugin/moteus_plugin/moteus_plugin.py index 96ca256f..ad58b046 100644 --- a/src/moteus_plugin/moteus_plugin/moteus_plugin.py +++ b/src/moteus_plugin/moteus_plugin/moteus_plugin.py @@ -1,20 +1,68 @@ -import sys -from PySide6.QtWidgets import QApplication, QMainWindow, QWidget -from PySide6.QtCore import QFile -from ui_moteus_plugin import Ui_Form +#!/usr/bin/env python3 +import os +import rospkg +# import rospy +from qt_gui.plugin import Plugin +from python_qt_binding import loadUi +from python_qt_binding.QtWidgets import QWidget -class Form(QWidget): - def __init__(self): - super(Form, self).__init__() - self.ui = Ui_Form() - self.ui.setupUi(self) +class MoteusPlugin(Plugin): + def __init__(self, context): + super(MoteusPlugin, self).__init__(context) + # Give QObjects reasonable names + self.setObjectName('MoteusPlugin') + rp = rospkg.RosPack() -if __name__ == "__main__": - app = QApplication(sys.argv) + # Process standalone plugin command-line arguments + from argparse import ArgumentParser + parser = ArgumentParser() + # Add argument(s) to the parser. + parser.add_argument("-q", "--quiet", action="store_true", + dest="quiet", + help="Put plugin in silent mode") + args, unknowns = parser.parse_known_args(context.argv()) + if not args.quiet: + print('arguments: ', args) + print('unknowns: ', unknowns) - window = Form() - window.show() + # Create QWidget + self._widget = QWidget() - sys.exit(app.exec()) + ui_file = os.path.join('moteus_plugin.ui') + # ui_file = os.path.join(rp.get_path( + # 'moteus_plugin'), 'moteus_plugin', 'resource', 'moteus_plugin.ui') + + loadUi(ui_file, self._widget) + # Give QObjects reasonable names + self._widget.setObjectName('MoteusPluginWidget') + # Show _widget.windowTitle on left-top of each plugin (when + # it's set in _widget). This is useful when you open multiple + # plugins at once. Also if you open multiple instances of your + # plugin at once, these lines add number to make it easy to + # tell from pane to pane. + if context.serial_number() > 1: + self._widget.setWindowTitle( + self._widget.windowTitle() + (' (%d)' % context.serial_number())) + # Add widget to the user interface + context.add_widget(self._widget) + + def shutdown_plugin(self): + # TODO unregister all publishers here + pass + + def save_settings(self, plugin_settings, instance_settings): + # TODO save intrinsic configuration, usually using: + # instance_settings.set_value(k, v) + pass + + def restore_settings(self, plugin_settings, instance_settings): + # TODO restore intrinsic configuration, usually using: + # v = instance_settings.value(k) + pass + + # def trigger_configuration(self): + # Comment in to signal that the plugin has a way to configure + # This will enable a setting button (gear icon) in each dock widget title bar + # Usually used to open a modal configuration dialog diff --git a/src/moteus_plugin/package.xml b/src/moteus_plugin/package.xml index aee2a1f0..27d1706e 100644 --- a/src/moteus_plugin/package.xml +++ b/src/moteus_plugin/package.xml @@ -4,11 +4,11 @@ moteus_plugin 0.0.0 TODO: Package description - jmacuga + jmacuga TODO: License declaration rqt_gui_py + rqt_gui ament_copyright ament_flake8 @@ -17,5 +17,8 @@ ament_python + + + diff --git a/src/moteus_plugin/plugin.xml b/src/moteus_plugin/plugin.xml new file mode 100644 index 00000000..530ef8f2 --- /dev/null +++ b/src/moteus_plugin/plugin.xml @@ -0,0 +1,20 @@ + + + + An example Python GUI plugin to create a great user interface. + + + + + system-help + Great user interface to provide real value. + + + \ No newline at end of file diff --git a/src/moteus_plugin/setup.py b/src/moteus_plugin/setup.py index 905acc92..817aeec8 100644 --- a/src/moteus_plugin/setup.py +++ b/src/moteus_plugin/setup.py @@ -1,4 +1,6 @@ from setuptools import setup +import os +from glob import glob package_name = 'moteus_plugin' @@ -10,12 +12,14 @@ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), ('share/' + package_name, ['package.xml']), + ('share/' + package_name, ['plugin.xml']), + (os.path.join('share', package_name), glob('resource/*')) + ], install_requires=['setuptools'], zip_safe=True, maintainer='jmacuga', - maintainer_email='julia.macuga -@gmail.com', + maintainer_email='julia.macuga@gmail.com', description='TODO: Package description', license='TODO: License declaration', tests_require=['pytest'], From 4e2eea8d4bb29b5b0785145d6d2140640bd90580 Mon Sep 17 00:00:00 2001 From: jmacuga Date: Tue, 9 May 2023 22:37:10 +0200 Subject: [PATCH 3/3] plugin added to rqt --- .../moteus_plugin/moteus_plugin.py | 49 +------------------ src/moteus_plugin/plugin.xml | 2 +- 2 files changed, 2 insertions(+), 49 deletions(-) diff --git a/src/moteus_plugin/moteus_plugin/moteus_plugin.py b/src/moteus_plugin/moteus_plugin/moteus_plugin.py index ad58b046..2db2655c 100644 --- a/src/moteus_plugin/moteus_plugin/moteus_plugin.py +++ b/src/moteus_plugin/moteus_plugin/moteus_plugin.py @@ -1,8 +1,4 @@ #!/usr/bin/env python3 -import os -import rospkg -# import rospy - from qt_gui.plugin import Plugin from python_qt_binding import loadUi from python_qt_binding.QtWidgets import QWidget @@ -13,56 +9,13 @@ def __init__(self, context): super(MoteusPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MoteusPlugin') - rp = rospkg.RosPack() - - # Process standalone plugin command-line arguments - from argparse import ArgumentParser - parser = ArgumentParser() - # Add argument(s) to the parser. - parser.add_argument("-q", "--quiet", action="store_true", - dest="quiet", - help="Put plugin in silent mode") - args, unknowns = parser.parse_known_args(context.argv()) - if not args.quiet: - print('arguments: ', args) - print('unknowns: ', unknowns) - # Create QWidget self._widget = QWidget() - - ui_file = os.path.join('moteus_plugin.ui') - # ui_file = os.path.join(rp.get_path( - # 'moteus_plugin'), 'moteus_plugin', 'resource', 'moteus_plugin.ui') - + ui_file = "src/moteus_plugin/moteus_plugin/moteus_plugin.ui" loadUi(ui_file, self._widget) # Give QObjects reasonable names - self._widget.setObjectName('MoteusPluginWidget') - # Show _widget.windowTitle on left-top of each plugin (when - # it's set in _widget). This is useful when you open multiple - # plugins at once. Also if you open multiple instances of your - # plugin at once, these lines add number to make it easy to - # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle( self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) - - def shutdown_plugin(self): - # TODO unregister all publishers here - pass - - def save_settings(self, plugin_settings, instance_settings): - # TODO save intrinsic configuration, usually using: - # instance_settings.set_value(k, v) - pass - - def restore_settings(self, plugin_settings, instance_settings): - # TODO restore intrinsic configuration, usually using: - # v = instance_settings.value(k) - pass - - # def trigger_configuration(self): - # Comment in to signal that the plugin has a way to configure - # This will enable a setting button (gear icon) in each dock widget title bar - # Usually used to open a modal configuration dialog diff --git a/src/moteus_plugin/plugin.xml b/src/moteus_plugin/plugin.xml index 530ef8f2..89b4d40a 100644 --- a/src/moteus_plugin/plugin.xml +++ b/src/moteus_plugin/plugin.xml @@ -12,7 +12,7 @@ --> - + system-help Great user interface to provide real value.