纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

Matplotlib绘制动态实时曲线 关于Matplotlib绘制动态实时曲线的方法改进指南

脑荼地   2021-06-07 我要评论
想了解关于Matplotlib绘制动态实时曲线的方法改进指南的相关内容吗脑荼地在本文为您仔细讲解Matplotlib绘制动态实时曲线的相关知识和一些Code实例欢迎阅读和指正我们先划重点:matplotlib实时动态图,matplotlib动态绘图,matplotlib库下面大家一起来学习吧

很多时候我们需要实时的绘制曲线如实时的绘制串口接收到的数据最先想到的解决策略是类似于Matlab种的drawnow函数

在python中Matplotlib库有着和Matlan绘图库相似的功能但是并没有drawnow这样的函数

已有的解决方案

通过网上现有的资料 基于Python实现matplotlib中动态更新图片(交互式绘图) 可以通过打开Matplotlib的交互模式来实现实时绘图的目的此时需要用到函数matplotlib.pyplot.ion

存在的问题

通过上述方法实时绘图存在一个严重的问题:随着时间推移CPU消耗越大费时越多最终导致程序卡顿这显然无法满足我们实时绘图的要求

以下通过time模块计算每一步的耗时直观地表现这一现象

def Method(point):
   es_time = np.zeros([point]) 
   fig=plt.figure()
   ax=fig.add_subplot(1,1,1)
   ax.axis("equal") #设置图像显示的时候XY轴比例
   ax.set_xlabel('Horizontal Position')
   ax.set_ylabel('Vertical Position')
   ax.set_title('Vessel trajectory')
   plt.grid(True) #添加网格
   plt.ion()  #interactive mode on
   IniObsX=0000
   IniObsY=4000
   IniObsAngle=135
   IniObsSpeed=10*math.sqrt(2)   #米/秒
   print('开始仿真')
   for t in range(point):
       t0 = time.time()
       #障碍物船只轨迹
       obsX=IniObsX+IniObsSpeed*math.sin(IniObsAngle/180*math.pi)*t
       obsY=IniObsY+IniObsSpeed*math.cos(IniObsAngle/180*math.pi)*t
       ax.scatter(obsX,obsY,c='b',marker='.')  #散点图
       #下面的图,两船的距离
       plt.pause(0.001)
       es_time[t] = 1000*(time.time() - t0)
   return es_time

耗时结果


Method

很显然每步绘图时间与绘图点数呈线性相关的趋势且随着点数增加时间消耗越多可以想象当绘图的点数到达上万乃至亿的时候那电脑就卡住了

分析原因

个人猜测出现上述这种现象的原因是由代码ax.scatter(obsX,obsY,c='b',marker='.')造成的这段代码每一循环一次就新画一条曲线而不清除之前的曲线这就必然导致越往后循环所花费的CPU资源内存资源越多最终机器卡死

改进方法

既然原因是因为不断重复画图所致导致机器资源的累积消耗所以想到的第一个解决方法那就是每次画图前清除之前的曲线

根据上述思想在每一次的画图代码ax.scatter(obsX,obsY,c='b',marker='.')前加上清除代码plt.cla()即:

        plt.cla()
        ax.plot(obsX,obsY,'-g',marker='*')  #散点图

可是这样做之后就会存在新的问题:之前定义的坐标轴标题图例等等信息就都被清除了解决方法则需要在每一步的循环中重新定义这些信息

完整代码

def Method_Improve(point):
    def initial(ax):
        ax.axis("equal") #设置图像显示的时候XY轴比例
        ax.set_xlabel('Horizontal Position')
        ax.set_ylabel('Vertical Position')
        ax.set_title('Vessel trajectory')
        plt.grid(True) #添加网格
        return ax
    
    es_time = np.zeros([point]) 
    fig=plt.figure()
    ax=fig.add_subplot(1,1,1)
    ax = initial(ax)
    plt.ion()  #interactive mode on
    IniObsX=0000
    IniObsY=4000
    IniObsAngle=135
    IniObsSpeed=10*math.sqrt(2)   #米/秒
    print('开始仿真')
    obsX = [0,]
    obsY = [4000,]
    for t in range(point):
        t0 = time.time()
        #障碍物船只轨迹
        obsX.append(IniObsX+IniObsSpeed*math.sin(IniObsAngle/180*math.pi)*t)
        obsY.append(IniObsY+IniObsSpeed*math.cos(IniObsAngle/180*math.pi)*t)
        plt.cla()
        ax = initial(ax)
        ax.plot(obsX,obsY,'-g',marker='*')  #散点图
        #下面的图,两船的距离
        plt.pause(0.001)
        es_time[t] = 1000*(time.time() - t0)
    return es_time

耗时结果


Method_Improve

显然循环次数与耗时不再呈正相关趋势可以说是在一定误差范围内耗时保持稳定

改进方法的改进

改进方法中仍存在一个问题:由于每次循环都需要清除坐标轴信息那么每次循环也必须再重新设置坐标轴信息显然这种做法导致了额外的算力消耗那能否有新的方法规避这种问题呢?答案显然是有的

但是解决思路还是得从原始问题出发即重复画图导致资源的累积消耗所以令一种新的思路:只画一条(需要数量的)曲线每次循环更改这些曲线的数据

那么按照上述思路之后只需程序开头定义好坐标轴信息而不需要每次循环内清除重设坐标轴信息

具体做法就是获取曲线的句柄进行修改即有:

        line.set_xdata(obsX)
        line.set_ydata(obsY)

完整代码:

def ImprovedMethod_Improve(point):    
    es_time = np.zeros([point]) 
    fig=plt.figure()
    ax=fig.add_subplot(1,1,1)

    ax.set_xlabel('Horizontal Position')
    ax.set_ylabel('Vertical Position')
    ax.set_title('Vessel trajectory')
    
    line = ax.plot([0,0],[4000,4000],'-g',marker='*')[0]
    plt.grid(True) #添加网格
    plt.ion()  #interactive mode on
    IniObsX=0000
    IniObsY=4000
    IniObsAngle=135
    IniObsSpeed=10*math.sqrt(2)   #米/秒
    print('开始仿真')
    obsX = [0,]
    obsY = [4000,]
    for t in range(point):
        t0 = time.time()
        #障碍物船只轨迹
        obsX.append(IniObsX+IniObsSpeed*math.sin(IniObsAngle/180*math.pi)*t)
        obsY.append(IniObsY+IniObsSpeed*math.cos(IniObsAngle/180*math.pi)*t)
        
        line.set_xdata(obsX)
        line.set_ydata(obsY)
        ax.set_xlim([-200,10*point+200])
        ax.set_ylim([3800-10*point,4200])
        #下面的图,两船的距离
        plt.pause(0.001)
        es_time[t] = 1000*(time.time() - t0)
    return es_time


三种方法对比

总结


相关文章

猜您喜欢

  • Java 内存安全问题 Java 内存安全问题的注意事项

    想了解Java 内存安全问题的注意事项的相关内容吗月伴飞鱼在本文为您仔细讲解Java 内存安全问题的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Java,内存问题,Java,内存安全下面大家一起来学习吧..
  • C++右值引用 详解C++右值引用

    想了解详解C++右值引用的相关内容吗可可西在本文为您仔细讲解C++右值引用的相关知识和一些Code实例欢迎阅读和指正我们先划重点:c++,右值引用下面大家一起来学习吧..

网友评论

Copyright 2020 www.fresh-weather.com 【世纪下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式