前言 这个博文可以说是承接前几篇的MPU6050数据读取、姿态解算,这里主要是实现姿态的可视化(也是课程作业要求,爬了)。
鉴于博主喜欢摸鱼的特点,这个实现也是ddl前几天完成的,由于网上没找到具体实现,只好用极坐标这个沙雕方法硬算出来。
将matplotlib嵌入PyQt5 matplotlib提供了在Qt中进行显示的一个backend(应该是?),这个方法基本上是网上统一这么实现(狗头)。
将matplotlib嵌入PyQt5一般是将其下面的matplotlib.backends.backend_qt5agg中的FigureCanvasQTAgg作为一个自己创建的类(可以理解为画布)(如这里的MyFigure)的父类,然后将自己创建的MyFigure类作为一个Widget放入QMainWindow或其他容器中(如QGroupBox)。
这里的代码是直接根据这篇博文进行修改的。
import matplotlib
matplotlib.use("Qt5Agg")# 声明使用QT5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MyFigure(FigureCanvas):
def __init__(self, width=5, height=4, dpi=100):
# 第一步:创建一个创建Figure
self.fig = Figure(figsize=(width, height), dpi=dpi)
# 第二步:在父类中激活Figure窗口
super(MyFigure, self).__init__(self.fig)# 此句必不可少,否则不能显示图形
self.ax = self.fig.add_subplot(111)#放置坐标系
self.ax.plot([0,1,2,3],[0,1,2,3],'c--')
将子类创建完毕后,我们需要进行实例化,然后将其放置到容器中,这里代码还是直接搬了一部分:
from PyQt5 import QtCore, QtGui, QtWidgetsimport matplotlib
matplotlib.use("Qt5Agg")# 声明使用QT5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox.setGeometry(QtCore.QRect(39, 29, 731, 421))
self.groupBox.setObjectName("groupBox")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.fig = MyFigure(3, 3, 100)
self.fig.suptitle("testfig")
QtWidgets.QGridLayout(self.groupBox).addWidget(self.fig)def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.groupBox.setTitle(_translate("MainWindow", "GroupBox"))
class MyFigure(FigureCanvas):
def __init__(self, width=5, height=4, dpi=100):
# 第一步:创建一个创建Figure
self.fig = Figure(figsize=(width, height), dpi=dpi)
# 第二步:在父类中激活Figure窗口
super(MyFigure, self).__init__(self.fig)# 此句必不可少,否则不能显示图形
self.ax = self.fig.add_subplot(111)#放置坐标系
self.ax.plot([0,1,2,3],[0,1,2,3],'c--')
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
QMainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(QMainWindow)
QMainWindow.show()
sys.exit(app.exec_())
使用matplotlib绘制动态曲线 【开发备忘|利用matplotlib和PyQt5绘制姿态球】使用matplotlib绘制动态曲线目前个人了解到的有4中方式,其中有两种我并未实践过,就不多进行介绍,大家可以参考这篇博文
1. 通过清理绘图区重绘 这种方式和第二种方式我都没进行过实际测试,只简单陈述一下:
大体就是先清除绘图区,再plot,再重绘并刷新
self.axes.cla()# 清除绘图区
self.axes.plot(t, s, 'o-r', linewidth=0.5)
self.figs.canvas.draw()# 这里注意是画布重绘,self.figs.canvas
self.figs.canvas.flush_events()# 画布刷新self.figs.canvas
2.通过清理画布重绘 单纯清除绘图区无法改变背景等设置,如果需要改变背景,那么需要清理画布,只需要改为:
self.figs.clf()# 清理画布,这里是clf()
self.axes = self.figs.add_subplot(111)# 清理画布后必须重新添加绘图区
self.axes.plot(t, s, 'o-r', linewidth=0.5)
self.figs.canvas.draw()# 这里注意是画布重绘,self.figs.canvas
self.figs.canvas.flush_events()# 画布刷新self.figs.canvas
3.通过设置数据重绘 这个是我一开始使用PyQt绘制动态曲线使用的方法,但是这个方法我只能实现一个动态曲线的绘制,而使用姿态球我需要进行fill填充操作,因此最后改为animation实现。
这个设置数据重绘我只实现了基于matplotlib.lines.Line2D的重绘,大致就是:
先导入这个类
from matplotlib.lines import Line2D
然后在前面实现的MyFigure类中加入该曲线,这里方便看又把代码搬过来了。
class MyFigure(FigureCanvas):
def __init__(self, width=5, height=4, dpi=100):
# 第一步:创建一个创建Figure
self.fig = Figure(figsize=(width, height), dpi=dpi)
# 第二步:在父类中激活Figure窗口
super(MyFigure, self).__init__(self.fig)# 此句必不可少,否则不能显示图形
self.ax = self.fig.add_subplot(111)#放置坐标系F = MyFigure()
xlist = [i for i in range(0,4,1)]
ylist = [2*ifor i in range(0,4,1)]
lineaz = Line2D(xlist, ylist)
lineaz.set_color('b')
F.ax.add_line(lineaz)
完成初始绘制之后,要想更新曲线,只需要重新设置x和y的值即可,不过如果想要写随时间变化的曲线,还需要做的一件事就是更改显示的范围,这个就是最后一行代码实现的功能。
lineaz.set_xdata(new_xlist)
lineaz.set_ydata(new_ylist)
F.ax.set_xlim(new_xlist[0],new_xlist[-1])
4.通过animation重绘 这个地方我在fill那里有个操作还没弄明白,先挖个坑,有时间再填
姿态球实现 姿态球表示 这个是借鉴dji的姿态球写的,大致是使用单独线段/箭头在极坐标中画出Yaw角,然后使用分界线的倾斜程度表示Roll角,根据填充比例表示Pitch角。示意图大概就是:
文章图片
算法逻辑 首先偏航角Yaw和剩余两个角度是分开计算的,偏航角Yaw非常容易表示,只需要从原点到(Yaw,设置的最大半径)连线即可。
然后的Roll角和Pitch角。Roll角和Pitch角是关联表示的,总体就是涂蓝的区域,而Roll角可以通过绿色线段的倾斜程度表示。
这个区域的计算逻辑是:
- 根据Pitch角,将其与90度对比,取得比值再乘以极坐标图的最大半径获得值x,那么(0,x)就为绿色直线上的点。
- 通过三角函数关系解算出直线与最大半径圆的焦点坐标,示意图大概是这样
文章图片
- 根据解算出的交点角度,在中间划分一定数目的点,然后连接线段/进行填充
实现结果
文章图片
推荐阅读
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- Python专栏|数据分析的常规流程
- Python|Win10下 Python开发环境搭建(PyCharm + Anaconda) && 环境变量配置 && 常用工具安装配置
- Python绘制小红花
- Pytorch学习|sklearn-SVM 模型保存、交叉验证与网格搜索
- OpenCV|OpenCV-Python实战(18)——深度学习简介与入门示例
- python|8. 文件系统——文件的删除、移动、复制过程以及链接文件
- 爬虫|若想拿下爬虫大单,怎能不会逆向爬虫,价值过万的逆向爬虫教程限时分享
- 分布式|《Python3网络爬虫开发实战(第二版)》内容介绍
- java|微软认真聆听了开源 .NET 开发社区的炮轰( 通过CLI 支持 Hot Reload 功能)