0

我在 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()您可以看到原始图。

4

1 回答 1

3

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

# 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 函数以比你正在做的更好的方式积分微分方程(这被称为欧拉积分,而且真的很容易出错)

于 2012-12-08T13:57:16.623 回答