Reputation: 21
I am using pyqtgraph.opengl for graphics and display of STL files on my UI. I am using phong shading technique called 'shaded' param with pyqtgraph.opengl.GLMeshItem API. But I am having a dark color shade projection more just like the following person posted in the link. Barrett Anderies issues with pyqtgraph dark images
The following is my dark shaded image below:
It seems like the light source is coming from below. I want to move this light source in the camera point of view. I am not sure how as I couldn't find any specific API on the documentation. pyqt5 documentation
This is my UI code for displaying stl files:
#!/usr/bin/env python3
import sys
import rclpy
from rclpy.qos import QoSProfile
from geometry_msgs.msg import Point
from std_msgs.msg import Bool
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QLineEdit, QVBoxLayout, QLabel, QMenuBar, QStatusBar, QOpenGLWidget
from PyQt5 import QtCore , QtGui
import pyqtgraph.opengl as gl
import numpy as np
from stl import mesh
import OpenGL.GL as ogl # Import the OpenGL module from PyOpenGL
class GLViewWidgetWithBackground(gl.GLViewWidget):
def __init__(self, parent=None):
super().__init__(parent)
# Ensure the clear color is set during initialization
self.setBackgroundColor(QtGui.QColor(85, 126, 214))
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1007, 730)
font = QtGui.QFont()
font.setPointSize(13)
MainWindow.setFont(font)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.calibrate_button = QPushButton(self.centralwidget)
self.calibrate_button.setGeometry(QtCore.QRect(50, 350, 89, 25))
self.calibrate_button.setObjectName("calibrate_button")
self.move_button = QPushButton(self.centralwidget)
self.move_button.setGeometry(QtCore.QRect(50, 280, 89, 25))
self.move_button.setObjectName("move_button")
self.stop_button = QPushButton(self.centralwidget)
self.stop_button.setGeometry(QtCore.QRect(170, 280, 89, 25))
self.stop_button.setObjectName("stop_button")
self.x_input = QLineEdit(self.centralwidget)
self.x_input.setGeometry(QtCore.QRect(10, 60, 51, 21))
self.x_input.setText("")
self.x_input.setObjectName("x_input")
self.y_input = QLineEdit(self.centralwidget)
self.y_input.setGeometry(QtCore.QRect(80, 60, 51, 21))
self.y_input.setText("")
self.y_input.setObjectName("y_input")
self.z_input = QLineEdit(self.centralwidget)
self.z_input.setGeometry(QtCore.QRect(150, 60, 51, 21))
self.z_input.setText("")
self.z_input.setObjectName("z_input")
self.publish_coords_button = QPushButton(self.centralwidget)
self.publish_coords_button.setGeometry(QtCore.QRect(220, 60, 89, 25))
self.publish_coords_button.setObjectName("publish_coords_button")
self.theta1 = QLineEdit(self.centralwidget)
self.theta1.setGeometry(QtCore.QRect(10, 180, 51, 21))
self.theta1.setObjectName("theta1")
self.theta2 = QLineEdit(self.centralwidget)
self.theta2.setGeometry(QtCore.QRect(80, 180, 51, 21))
self.theta2.setObjectName("theta2")
self.theta3 = QLineEdit(self.centralwidget)
self.theta3.setGeometry(QtCore.QRect(150, 180, 51, 21))
self.theta3.setObjectName("theta3")
self.publish_angles_button = QPushButton(self.centralwidget)
self.publish_angles_button.setGeometry(QtCore.QRect(220, 180, 89, 25))
font = QtGui.QFont()
font.setPointSize(13)
self.publish_angles_button.setFont(font)
self.publish_angles_button.setObjectName("publish_angles_button")
self.min_q1 = QLabel(self.centralwidget)
self.min_q1.setGeometry(QtCore.QRect(10, 210, 61, 21))
font = QtGui.QFont()
font.setPointSize(8)
self.min_q1.setFont(font)
self.min_q1.setObjectName("min_q1")
self.max_q1 = QLabel(self.centralwidget)
self.max_q1.setGeometry(QtCore.QRect(10, 150, 61, 21))
font = QtGui.QFont()
font.setPointSize(8)
self.max_q1.setFont(font)
self.max_q1.setObjectName("max_q1")
self.min_q2 = QLabel(self.centralwidget)
self.min_q2.setGeometry(QtCore.QRect(80, 210, 81, 21))
font = QtGui.QFont()
font.setPointSize(8)
self.min_q2.setFont(font)
self.min_q2.setObjectName("min_q2")
self.max_q2 = QLabel(self.centralwidget)
self.max_q2.setGeometry(QtCore.QRect(80, 150, 81, 21))
font = QtGui.QFont()
font.setPointSize(8)
self.max_q2.setFont(font)
self.max_q2.setObjectName("max_q2")
self.min_t3 = QLabel(self.centralwidget)
self.min_t3.setGeometry(QtCore.QRect(150, 210, 51, 16))
font = QtGui.QFont()
font.setPointSize(8)
self.min_t3.setFont(font)
self.min_t3.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft)
self.min_t3.setObjectName("min_t3")
self.max_t3 = QLabel(self.centralwidget)
self.max_t3.setGeometry(QtCore.QRect(150, 150, 61, 21))
font = QtGui.QFont()
font.setPointSize(8)
self.max_t3.setFont(font)
self.max_t3.setObjectName("max_t3")
self.ManualMode = QPushButton(self.centralwidget)
self.ManualMode.setGeometry(QtCore.QRect(170, 350, 89, 25))
self.ManualMode.setObjectName("ManualMode")
# 3D view widget
self.openGLWidget = GLViewWidgetWithBackground(self.centralwidget)
self.openGLWidget.setGeometry(QtCore.QRect(340, 60, 641, 621))
self.openGLWidget.setObjectName("openGLWidget")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1007, 25))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.calibrate_button.setText(_translate("MainWindow", "Calibrate"))
self.move_button.setText(_translate("MainWindow", "Move"))
self.stop_button.setText(_translate("MainWindow", "STOP"))
self.x_input.setPlaceholderText(_translate("MainWindow", "x"))
self.y_input.setPlaceholderText(_translate("MainWindow", "y"))
self.z_input.setPlaceholderText(_translate("MainWindow", "z"))
self.publish_coords_button.setText(_translate("MainWindow", "Set IK"))
self.theta1.setPlaceholderText(_translate("MainWindow", "q1"))
self.theta2.setPlaceholderText(_translate("MainWindow", "q2"))
self.theta3.setPlaceholderText(_translate("MainWindow", "t3"))
self.publish_angles_button.setText(_translate("MainWindow", "Set FK"))
self.min_q1.setText(_translate("MainWindow", "min: -40"))
self.max_q1.setText(_translate("MainWindow", "max: 40"))
self.min_q2.setText(_translate("MainWindow", "min: -29.24"))
self.max_q2.setText(_translate("MainWindow", "max: 50.17"))
self.min_t3.setText(_translate("MainWindow", "min: 0"))
self.max_t3.setText(_translate("MainWindow", "max: 150"))
self.ManualMode.setText(_translate("MainWindow", "Manual"))
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
# self.setStyleSheet("background-color: cyan;") # Set the background color here
# Initialize ROS node
rclpy.init()
# Create ROS publisher
self.node = rclpy.create_node('gui_publisher')
qos = QoSProfile(depth=10)
self.pub_cal = self.node.create_publisher(Bool, 'cal_click', qos)
self.pub_move = self.node.create_publisher(Bool, 'move_click', qos)
self.pub_manual = self.node.create_publisher(Bool, 'manual_click', qos)
self.pub_stop = self.node.create_publisher(Bool, 'stop_click', qos)
self.pub_coords = self.node.create_publisher(Point, 'coordinates', qos)
self.pub_angles = self.node.create_publisher(Point, 'angles', qos)
self.pub_close = self.node.create_publisher(Bool, 'close_click', qos)
# Connect button clicks to methods
self.calibrate_button.clicked.connect(self.on_calibrate_clicked)
self.move_button.clicked.connect(self.on_move_clicked)
self.ManualMode.clicked.connect(self.on_manual_clicked)
self.stop_button.clicked.connect(self.on_stop_clicked)
self.publish_coords_button.clicked.connect(self.on_publish_coords_clicked)
self.publish_angles_button.clicked.connect(self.on_publish_angles_clicked)
self.show()
# Define colors
white_color = [253/255.0, 253/255.0, 253/255.0, 0.9]
purple_transparent = [128/255.0, 0, 128/255.0, 1.0]
edgeColor_white = [140/255.0, 140/255.0, 140/255.0, 1.0]
edgeColor_purple = [120/255.0, 0, 120/255.0, 1.0]
# # Load STL files with specified colors
stl_files = [
("/home/nagarjun/ros2_ws/src/robot_parts/ROT_Link_v2.STL", white_color, edgeColor_white),
("/home/nagarjun/ros2_ws/src/robot_parts/Nut_v2.STL", white_color, edgeColor_white),
("/home/nagarjun/ros2_ws/src/robot_parts/RCM_CenterLink_v2.STL", white_color, edgeColor_white),
("/home/nagarjun/ros2_ws/src/robot_parts/RCM_SwingArm_Back_v2.STL", white_color, edgeColor_white),
("/home/nagarjun/ros2_ws/src/robot_parts/RCM_Parallelogram_Up_v2.STL", white_color, edgeColor_white),
("/home/nagarjun/ros2_ws/src/robot_parts/RCM_Parallelogram_Down_v2.STL", white_color, edgeColor_white),
("/home/nagarjun/ros2_ws/src/robot_parts/RCM_SwingArm_Front_v2.STL", white_color, edgeColor_white),
("/home/nagarjun/ros2_ws/src/robot_parts/NeedleHolder_v2.STL", white_color, edgeColor_white),
("/home/nagarjun/ros2_ws/src/robot_parts/Needle_v2.STL", white_color, edgeColor_white),
("/home/nagarjun/ros2_ws/src/robot_parts/Frame_v2.STL", purple_transparent, edgeColor_purple)
]
for stl_file, color, edgeColor in stl_files:
self.load_stl(stl_file,color, edgeColor)
def on_calibrate_clicked(self):
msg = Bool()
msg.data = True
self.pub_cal.publish(msg)
print("Cal Click")
def on_move_clicked(self):
msg = Bool()
msg.data = True
self.pub_move.publish(msg)
print("Move Click")
def on_manual_clicked(self):
msg = Bool()
msg.data = True
self.pub_manual.publish(msg)
print("Manual Click")
def on_stop_clicked(self):
msg = Bool()
msg.data = True
self.pub_stop.publish(msg)
print("Stop button clicked!")
def on_publish_coords_clicked(self):
x = float(self.x_input.text())
y = float(self.y_input.text())
z = float(self.z_input.text())
msg = Point()
msg.x = x
msg.y = y
msg.z = z
self.pub_coords.publish(msg)
print(f"Published Coordinates: x={x}, y={y}, z={z}")
def on_publish_angles_clicked(self):
q1 = float(self.theta1.text())
q2 = float(self.theta2.text())
t3 = float(self.theta3.text())
msg = Point()
msg.x = q1
msg.y = q2
msg.z = t3
self.pub_angles.publish(msg)
print(f"Published angles: q1={q1}, q2={q2}, t3={t3}")
def closeEvent(self, event):
msg = Bool()
msg.data = True
self.pub_close.publish(msg)
super().closeEvent(event)
def load_stl(self, filepath, color, edgeColor):
your_mesh = mesh.Mesh.from_file(filepath)
# each vertex is a 3 coordinates
vertices = np.zeros((your_mesh.vectors.size, 3))
# Each face (triangle) is represented by three vertex indices, hence the shape[0] which is no. of vertices
faces = np.zeros((your_mesh.vectors.shape[0], 3), dtype=int)
vertex_id = 0
#This loop iterates over each triangle in the mesh.
for i, v in enumerate(your_mesh.vectors):
#This nested loop iterates over each vertex of the current triangle.
for j in range(3):
#This line assigns the coordinates of the current vertex 'v[j, :]' to the vertices array at the position vertex_id.
vertices[vertex_id, :] = v[j, :]
faces[i, j] = vertex_id
vertex_id += 1
# Define white color with full opacity
colors = np.array([color] * faces.shape[0])
mesh_item = gl.GLMeshItem(vertexes=vertices, faces=faces, edgeColor = edgeColor, drawEdges=False, drawFaces=True, shader='shaded' ,smooth=False, faceColors=colors)
self.openGLWidget.addItem(mesh_item)
def main():
# create pyqt5 app
app = QApplication(sys.argv)
# create the instance of our Window
window = MainWindow()
window.show()
# start the app
sys.exit(app.exec())
if __name__ == '__main__':
main()
The have tried using vertex shader and fragment shader but I still dont have any better results.
I am expecting the light should come from camera point of view... Like if I can change the position of the light source.
Upvotes: 1
Views: 123