2012-12-06 3 views
0

У меня есть несколько графиков линий, которые нанесены на одни и те же оси в Matplotlib. Я пытаюсь использовать виджет слайдера для настройки линии, но по какой-то причине, только первая линия участок, показывающий, и ничего не обновляется при перемещении ползунка:Использование ползунков Matplotlib с несколькими графиками на тех же осях

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() вы можете увидеть оригинальные сюжеты.

ответ

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, чтобы лучше интегрировать дифференциальное уравнение, чем то, что вы делаете (что называется интеграцией Эйлера, и действительно подвержено ошибкам) ​​

+0

Отлично - спасибо! Я просто расширил пример slider_demo.py в документах Matplotlib (http://matplotlib.org/examples/widgets/slider_demo.html), но ваш подход с использованием subplot2grid намного яснее. – Gerrit

Смежные вопросы