|
@@ -0,0 +1,283 @@
|
|
|
+import os
|
|
|
+import subprocess
|
|
|
+
|
|
|
+from PyQt5.QtWidgets import (QWidget,QVBoxLayout,QTabWidget,QSplitter, QFileDialog,QMessageBox,QComboBox,
|
|
|
+ QLineEdit,QTextEdit,QCheckBox,QLabel,QFrame,QPushButton,QMenu,QAction)
|
|
|
+from PyQt5.QtGui import QPixmap,QImage,QPainter,QResizeEvent,QCloseEvent,QPaintEvent
|
|
|
+from PyQt5.QtCore import QRect,Qt
|
|
|
+import numpy as np
|
|
|
+import def_pb2 as pb
|
|
|
+import GrpcClient as rpc
|
|
|
+import vtk
|
|
|
+from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
|
|
|
+#from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
|
|
|
+
|
|
|
+import threading
|
|
|
+import json
|
|
|
+class ControlFrame(QFrame):
|
|
|
+ def __init__(self):
|
|
|
+ QFrame.__init__(self)
|
|
|
+ with open("./ui_config.json",'r',encoding='utf-8') as fp:
|
|
|
+ self.config=json.load(fp)
|
|
|
+ self.setGeometry(0, 0, 500, 500)
|
|
|
+ self.InitUI()
|
|
|
+ self.setFrameShape(self.StyledPanel)
|
|
|
+
|
|
|
+ def OnAction(self,dtype,id):
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.config[self.IPcombox.currentText()]
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ try:
|
|
|
+ if dtype==1:
|
|
|
+ client.GrabImage(ip,port,id)
|
|
|
+ if dtype==2:
|
|
|
+ client.GrabCloud(ip,port,id)
|
|
|
+ except Exception as e:
|
|
|
+ QMessageBox.information(self, 'ERROR',str(e),QMessageBox.Ok,QMessageBox.Ok)
|
|
|
+
|
|
|
+ def InitUI(self):
|
|
|
+
|
|
|
+ self.begstatic = QLabel(self)
|
|
|
+ self.begstatic.setText(" IP:")
|
|
|
+ self.begstatic.setGeometry(20, 5, 80, 25)
|
|
|
+ self.IPcombox = QComboBox(self)
|
|
|
+ self.IPcombox.addItems(self.config.keys())
|
|
|
+ self.IPcombox.setGeometry(90, 5, 150, 25)
|
|
|
+
|
|
|
+ self.endstatic = QLabel(self)
|
|
|
+ self.endstatic.setText("Port:")
|
|
|
+ self.endstatic.setGeometry(20, 35, 80, 25)
|
|
|
+ self.PortEdit = QLineEdit(self)
|
|
|
+ self.PortEdit.setText("9876")
|
|
|
+ self.PortEdit.setGeometry(90, 35, 150, 25)
|
|
|
+
|
|
|
+ self.btnDataStreamCheck = QCheckBox("实时显示", self)
|
|
|
+ self.btnDataStreamCheck.setGeometry(150, 65, 120, 30)
|
|
|
+ self.btnDataStreamCheck.clicked.connect(self.RealTimeDatacb)
|
|
|
+
|
|
|
+ self.staticError = QLabel(self)
|
|
|
+ self.staticError.setText("信息:")
|
|
|
+ self.staticError.setGeometry(20, 100, 230, 400)
|
|
|
+ self.staticError.setWordWrap(True)
|
|
|
+ self.staticError.setAlignment(Qt.AlignTop)
|
|
|
+ def DisplayErrorInfo(self,info):
|
|
|
+ self.staticError.setText("信息:"+info)
|
|
|
+ def RealTimeDatacb(self):
|
|
|
+ self.staticError.setText("信息:")
|
|
|
+ try:
|
|
|
+ if self.btnDataStreamCheck.checkState()==Qt.Checked:
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.config[self.IPcombox.currentText()]
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ client.OpenDataStream(ip,port)
|
|
|
+ else:
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.config[self.IPcombox.currentText()]
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ client.CloseDataStream(ip,port)
|
|
|
+ except Exception as e:
|
|
|
+ QMessageBox.information(self, 'ERROR',str(e),QMessageBox.Ok,QMessageBox.Ok)
|
|
|
+ def closeEvent(self, a0: QCloseEvent) -> None:
|
|
|
+ if self.btnDataStreamCheck.checkState()==Qt.Checked:
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.config[self.IPcombox.currentText()]
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ client.CloseDataStream(ip,port)
|
|
|
+ rpc.GrpcStream().close()
|
|
|
+
|
|
|
+class VtkPointCloud:
|
|
|
+ def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e7):
|
|
|
+ self.maxNumPoints = maxNumPoints
|
|
|
+ self.vtkPolyData = vtk.vtkPolyData()
|
|
|
+ self.clearPoints()
|
|
|
+ mapper = vtk.vtkPolyDataMapper()
|
|
|
+ mapper.SetInputData(self.vtkPolyData)
|
|
|
+ mapper.SetColorModeToDefault()
|
|
|
+ mapper.SetScalarRange(zMin, zMax)
|
|
|
+ mapper.SetScalarVisibility(1)
|
|
|
+ self.vtkActor = vtk.vtkActor()
|
|
|
+
|
|
|
+
|
|
|
+ self.vtkActor.SetMapper(mapper)
|
|
|
+ self.vtkActor.GetProperty().SetPointSize(1)
|
|
|
+ self.vtkActor.GetProperty().SetColor(1, 1, 1)
|
|
|
+
|
|
|
+ def addPoint(self, point):
|
|
|
+ if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints:
|
|
|
+ pointId = self.vtkPoints.InsertNextPoint(point)
|
|
|
+ self.vtkDepth.InsertNextValue(point[2])
|
|
|
+ self.vtkCells.InsertNextCell(1)
|
|
|
+ self.vtkCells.InsertCellPoint(pointId)
|
|
|
+ self.vtkCells.Modified()
|
|
|
+ self.vtkPoints.Modified()
|
|
|
+ self.vtkDepth.Modified()
|
|
|
+
|
|
|
+ def clearPoints(self):
|
|
|
+ self.vtkPoints = vtk.vtkPoints()
|
|
|
+ self.vtkCells = vtk.vtkCellArray()
|
|
|
+ self.vtkDepth = vtk.vtkDoubleArray()
|
|
|
+ self.vtkDepth.SetName('DepthArray')
|
|
|
+ self.vtkPolyData.SetPoints(self.vtkPoints)
|
|
|
+ self.vtkPolyData.SetVerts(self.vtkCells)
|
|
|
+ #self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
|
|
|
+ self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')
|
|
|
+
|
|
|
+class pclViewer(QVTKRenderWindowInteractor):
|
|
|
+ def __init__(self,parent=None):
|
|
|
+ super(pclViewer,self).__init__(parent=parent)
|
|
|
+ def mousePressEvent(self, ev):
|
|
|
+ btn = ev.button()
|
|
|
+ if btn == Qt.RightButton:
|
|
|
+ print(" r btn")
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ #QVTKRenderWindowInteractor.mousePressEvent(self,ev)
|
|
|
+
|
|
|
+
|
|
|
+class VtkPointCloudCanvas(QWidget):
|
|
|
+ def __init__(self, *args, **kwargs):
|
|
|
+ super(VtkPointCloudCanvas, self).__init__(*args, **kwargs)
|
|
|
+ self.lock_=threading.RLock()
|
|
|
+
|
|
|
+ self._layout = QVBoxLayout()
|
|
|
+ self.setLayout(self._layout)
|
|
|
+ self._vtk_widget = pclViewer(self)
|
|
|
+ self._vtk_widget.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera()) # 设置交互方式==常用的方式 移动摄像机
|
|
|
+
|
|
|
+ self._layout.addWidget(self._vtk_widget)
|
|
|
+
|
|
|
+ self._render = vtk.vtkRenderer()
|
|
|
+ self._vtk_widget.GetRenderWindow().AddRenderer(self._render)
|
|
|
+ self._iren = self._vtk_widget.GetRenderWindow().GetInteractor()
|
|
|
+ self._point_cloud = VtkPointCloud()
|
|
|
+ self._render.AddActor(self._point_cloud.vtkActor)
|
|
|
+
|
|
|
+ transform = vtk.vtkTransform()
|
|
|
+ transform.Translate(0, -0.1, 0.0)
|
|
|
+ axes = vtk.vtkAxesActor()
|
|
|
+ axes.SetUserTransform(transform)
|
|
|
+ axes.SetTotalLength([0.1,0.1,0])
|
|
|
+
|
|
|
+ axes.SetXAxisLabelText('x')
|
|
|
+ axes.SetYAxisLabelText('y')
|
|
|
+ axes.SetZAxisLabelText('')
|
|
|
+ colors = vtk.vtkNamedColors()
|
|
|
+ axes.GetXAxisCaptionActor2D().GetCaptionTextProperty().SetColor(colors.GetColor3d("Red"))
|
|
|
+ axes.GetYAxisCaptionActor2D().GetCaptionTextProperty().SetColor(colors.GetColor3d("Green"))
|
|
|
+ axes.GetZAxisCaptionActor2D().GetCaptionTextProperty().SetColor(colors.GetColor3d("Blue"))
|
|
|
+ self._render.AddActor(axes)
|
|
|
+
|
|
|
+ self.camera=self._render.GetActiveCamera()
|
|
|
+ self.show()
|
|
|
+ self._iren.Initialize()
|
|
|
+
|
|
|
+ def close(self) -> bool:
|
|
|
+ print(" tk close")
|
|
|
+ self._point_cloud.clearPoints()
|
|
|
+
|
|
|
+ def displayPCL(self,cloud:np.array):
|
|
|
+ colors = vtk.vtkUnsignedCharArray()
|
|
|
+ colors.SetNumberOfComponents(3)
|
|
|
+ colors.SetName("Colors")
|
|
|
+
|
|
|
+ self._point_cloud.clearPoints()
|
|
|
+ for point in cloud:
|
|
|
+ self._point_cloud.addPoint(point)
|
|
|
+ colors.InsertNextTypedTuple((255,255,255))
|
|
|
+ self._point_cloud.vtkPolyData.GetPointData().SetScalars(colors)
|
|
|
+ self._vtk_widget.update()
|
|
|
+ def resetViewer(self):
|
|
|
+ self.update()
|
|
|
+
|
|
|
+
|
|
|
+class PointCLViwer(QSplitter):
|
|
|
+ def __init__(self,OnAction,id):
|
|
|
+ super(PointCLViwer, self).__init__()
|
|
|
+ self.OnAction=OnAction
|
|
|
+ self.dtype=2
|
|
|
+ self.id=id
|
|
|
+ self.pointCloud=[]
|
|
|
+ self.InitUI()
|
|
|
+ def InitUI(self):
|
|
|
+ self.pclViewer=VtkPointCloudCanvas(self)
|
|
|
+ self.addWidget(self.pclViewer)
|
|
|
+ self.setStretchFactor(0,4)
|
|
|
+
|
|
|
+ def displayCloud(self,points:np.array):
|
|
|
+ self.pointCloud=points
|
|
|
+ self.pclViewer.displayPCL(points)
|
|
|
+ def resetViewer(self):
|
|
|
+ self.pclViewer.resetViewer()
|
|
|
+ def updataData(self):
|
|
|
+ self.OnAction(self.dtype,self.id-1)
|
|
|
+ def displayAllPoints(self):
|
|
|
+ self.pclViewer.displayPCL(self.pointCloud)
|
|
|
+ def contextMenuEvent(self, a0):
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+class ViewerFrame(QFrame):
|
|
|
+ def __init__(self,OnAction):
|
|
|
+ super(ViewerFrame, self).__init__()
|
|
|
+ self.OnAction=OnAction
|
|
|
+ self.InitUI()
|
|
|
+ def InitUI(self):
|
|
|
+
|
|
|
+ self.table1=QTabWidget(self)
|
|
|
+ self.table2=QTabWidget(self)
|
|
|
+ self.table3=QTabWidget(self)
|
|
|
+ self.table4=QTabWidget(self)
|
|
|
+ self.table1.setTabPosition(QTabWidget.TabPosition.North)
|
|
|
+ self.table2.setTabPosition(QTabWidget.TabPosition.North)
|
|
|
+ self.table3.setTabPosition(QTabWidget.TabPosition.North)
|
|
|
+ self.table4.setTabPosition(QTabWidget.TabPosition.North)
|
|
|
+
|
|
|
+ self.pcViewer1=PointCLViwer(self.OnAction,1)
|
|
|
+ self.pcViewer2=PointCLViwer(self.OnAction,2)
|
|
|
+ self.pcViewer3=PointCLViwer(self.OnAction,3)
|
|
|
+ self.pcViewer4=PointCLViwer(self.OnAction,4)
|
|
|
+
|
|
|
+ self.table1.addTab(self.pcViewer1,"C3")
|
|
|
+ self.table2.addTab(self.pcViewer2,"C4")
|
|
|
+ self.table3.addTab(self.pcViewer3,"C5")
|
|
|
+ self.table4.addTab(self.pcViewer4,"C6")
|
|
|
+
|
|
|
+ def closeEvent(self, a0: QCloseEvent) -> None:
|
|
|
+
|
|
|
+ pass
|
|
|
+ def resizeEvent(self, a0: QResizeEvent) -> None:
|
|
|
+ w, h = self.size().width(), self.size().height()
|
|
|
+ w=w-15
|
|
|
+ h=h-15
|
|
|
+ self.table1.setGeometry(5, 5, w/2, h/2)
|
|
|
+ self.table2.setGeometry(10+w/2, 5, w/2, h/2)
|
|
|
+ self.table3.setGeometry(5, 10+h/2, w/2, h/2)
|
|
|
+ self.table4.setGeometry(10+w/2, 10+h/2, w/2, h/2)
|
|
|
+
|
|
|
+ def PbCloud2Pts(self,cloud):
|
|
|
+ size=len(cloud)
|
|
|
+ npdata=np.zeros(shape=[size,3],dtype=np.float32)
|
|
|
+ i=0
|
|
|
+ for point in cloud:
|
|
|
+ x=point.x
|
|
|
+ y=point.y
|
|
|
+ npdata[i,:]=[x,y-0.1,0]
|
|
|
+ i=i+1
|
|
|
+ return npdata
|
|
|
+ def DisplayCloud(self,clouds:pb.clouds):
|
|
|
+ self.pcViewer1.displayCloud(self.PbCloud2Pts(clouds.clamp_1))
|
|
|
+ self.pcViewer2.displayCloud(self.PbCloud2Pts(clouds.clamp_2))
|
|
|
+ self.pcViewer3.displayCloud(self.PbCloud2Pts(clouds.clamp_3))
|
|
|
+ self.pcViewer4.displayCloud(self.PbCloud2Pts(clouds.clamp_4))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|