【问题标题】:Using Matplotlib sliders with multiple plots on the same axes将 Matplotlib 滑块与同一轴上的多个绘图一起使用
【发布时间】:2012-12-06 15:32:10
【问题描述】:

我在 Matplotlib 的同一轴上绘制了多条线图。我正在尝试使用 Slider 小部件来调整线条,但由于某种原因,只显示了第一条线图,并且当我移动滑块时没有任何更新:

import matplotlib.pyplot as p
from matplotlib.widgets import Slider, Button, RadioButtons

Kd=0.0 
Ks=0.0
mass=0.02 

width=900
yPosition = []
yVelocity = []
yTarget = []
yForce = []
lpos= []
lvel = []
ltarget = []
lforce = []

def runSimulation(positionGain=1.5, velocityGain=60.0):
    global Kd, Ks, mass, yPosition, yVelocity, yTarget, yForce, width

    velocity = 0.0
    acceleration = 0.0
    reference = 100.0
    target = 0.0
    position = 0.0
    force = 0.0
    T=0.0005

    yPosition = []
    yVelocity = []
    yTarget = []
    yForce = []

    for i in range(0,width*10):
        acceleration = (force - Kd*velocity - Ks*position)/mass

        # Equations of motion for constant acceleration
        position = position + (velocity*T) + (0.5*acceleration*T*T)
        velocity = velocity + acceleration*T 

        e1 = target - position # Output of 1st control system
        e2 = positionGain * e1 - velocity # Output of 2nd control system
        force = velocityGain * e2

        if i % 10 == 0: #Plot 1 point for every 10 iterations of simulation
            if i>=30:
                target = reference
            else:
                target = 0
            yPosition.append(position)
            yVelocity.append(velocity*0.1)
            yTarget.append(target)
            yForce.append(force*0.001)

def plotGraph():
    global yPosition, yVelocity, yTarget, yForce, lpos, lvel, ltarget, lforce
    x = range(0,width)
    ax = p.subplot(111)
    lpos, = ax.plot(x,yPosition,'r')
    lvel, = ax.plot(x,yVelocity,'g')
    ltarget, = ax.plot(x,yTarget,'k')
    lforce, = ax.plot(x,yForce,'b')

ax = p.subplot(111)
p.subplots_adjust(left=0.25, bottom=0.25)
runSimulation()
plotGraph()

p.axis([0, 1, -10, 10])

axcolor = 'lightgoldenrodyellow'
axpos = p.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
axvel  = p.axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)

spos = Slider(axpos, 'Position Gain', 1.0, 20.0, valinit=1.5)
svel = Slider(axvel, 'Velocity Gain', 5.0, 500.0, valinit=60.0)

def update(val):
    global yPosition,yVelocity,yTarget,yForce
    runSimulation(round(spos.val,2),round(svel.val,2))
    lpos.set_ydata(yPosition)
    lvel.set_ydata(yVelocity)
    ltarget.set_ydata(yTarget)
    lforce.set_ydata(yForce)
    p.draw()

spos.on_changed(update)
svel.on_changed(update)
p.show()

如果删除plotGraph()p.show() 之间的线,您可以看到原始图。

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    老实说,您在轴定位和更新功能方面有些混乱。我冒昧地再次写了绘图部分并将评论放在那里:

    # run your simulation like usual
    runSimulation()
    
    #create a ordered grid of axes, not one in top of the others
    axcolor = 'lightgoldenrodyellow'
    fig = p.figure()
    axdata = p.subplot2grid((7,4),(0,0),colspan=4,rowspan=4)
    axpos = p.subplot2grid((7,4),(-2,0),colspan=4, axisbg=axcolor)
    axvel = p.subplot2grid((7,4),(-1,0),colspan=4, axisbg=axcolor)
    
    # create your plots in the global space.
    # you are going to reference these lines, so you need to make them visible
    # to the update functione, instead of creating them inside a function 
    # (and thus losing them at the end of the function)
    x = range(width)
    lpos, = axdata.plot(x,yPosition,'r')
    lvel, = axdata.plot(x,yVelocity,'g')
    ltarget, = axdata.plot(x,yTarget,'k')
    lforce, = axdata.plot(x,yForce,'b')
    
    # same as usual
    spos = Slider(axpos, 'Position Gain', 1.0, 20.0, valinit=1.5)
    svel = Slider(axvel, 'Velocity Gain', 5.0, 500.0, valinit=60.0)
    
    
    def update(val):
        # you don't need to declare the variables global, as if you don't
        # assign a value to them python will recognize them as global
        # without problem
        runSimulation(round(spos.val,2),round(svel.val,2))
        lpos.set_ydata(yPosition)
        lvel.set_ydata(yVelocity)
        ltarget.set_ydata(yTarget)
        lforce.set_ydata(yForce)
        # you need to update only the canvas of the figure
        fig.canvas.draw()
    
    spos.on_changed(update)
    svel.on_changed(update)
    p.show()
    

    顺便说一下,如果你想模拟阻尼振荡,我强烈建议你看看 scipy 的积分模块,它包含 odeint 函数,可以比你正在做的更好的方式积分微分方程(这就是所谓的欧拉积分,确实很容易出错)

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 2022-01-19
    • 2015-10-18
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多