Related
Im having trouble getting two definitions to speak to each other using a UI. I would like to create a bunch of locators place them in the scene and name them. Then in a different definition create some joints and use the locators name and position to position the joints and name them according to the locators I previously created.
My problem is the variable named rootJnt is not being recognized in the joint creation definition. All others are except rootJnt. I don't understand why, all the other variables are being recognized. Can some one please explain?
from maya import cmds
def proxySkel (self):
target = cmds.ls (selection = True)
DDD = cmds.textField (textNam,
query = True,
text = True)
# CREATE THE LOCATOR
_endOutLoc = cmds.spaceLocator (position = (0, 0, 0), name = DDD + '_locEndOut')
_startOutLoc = cmds.spaceLocator (position = (0, 0, 0), name = DDD + '_locStartOut')
_rootLoc = cmds.spaceLocator (position = (0, 0, 0), name = DDD + '_locRoot')
# MOVE END LOCATOR IN SPACE
cmds.move (5, 0, 3, _endOutLoc, absolute = True)
cmds.move (0, 0, 3, _startOutLoc, absolute = True)
return _endOutLoc, _startOutLoc, _rootLoc
def jointsCreate (self):
target = cmds.ls (selection = True)
DDD = cmds.textField (textNam,
query = True,
text = True)
# CREATE THE JOINTS
rootJnt = cmds.joint (position = (0.0, 0.0, 0.0), name = _rootLoc + '_jnt')
endOutJnt = cmds.joint (position = (0.0, 0.0, 0.0), name = _endOutLoc[0] + '_jnt')
startOutJnt = cmds.joint (position = (0.0, 0.0, 0.0), name = _startOutLoc[0] + '_jnt')
# PLACE THE JOINTS INTO SPACE
rootConst = cmds.parentConstraint (_rootLoc, rootJnt, mo = False)
endOutConst = cmds.parentConstraint (_endOutLoc, endOutJnt, mo = False)
startInConst = cmds.parentConstraint (_startInLoc, startInJnt, mo = False)
# CREATE THE JOINT HIERARCHY
cmds.parent (startInJnt, rootJnt)
cmds.parent (startInJnt, startOutJnt)
if(cmds.window('window1',q=1,ex=1)):
cmds.deleteUI('window1')
cmds.window('window1',menuBar=1)
cmds.columnLayout()
textNam = cmds.textField(width=150,
text='Name',
backgroundColor=[0.6233005264362554, 1.0, 0.9765011062790875])
cmds.separator()
cmds.rowLayout(numberOfColumns=3)
cmds.button(width=65,
command = proxySkel,
backgroundColor=[0.0, 0.2187533379110399, 1.0],
label='Locators')
cmds.separator(style='none',
width=3)
cmds.button(width=78,
command = jointsCreate,
backgroundColor=[0.7971007858396277, 0.0, 0.0],
label='Joints')
cmds.showWindow('window1')
To have access to your variables between two functions, you have to define them in an outer scope. In your case _endOutLoc, _startOutLoc, _rootLoc are defined locally to ProxySkel function and they are not visible to jointsCreate function
In additional to that, there are several other mistakes
as it was mentioned in the comments to your question, _rootLoc have to be passed with index 0, because it stores value as a list, not as a string
if you are using parent constraint for the alignment, I would guess you want to delete them once the alignment is finished
there is no need to call parent command for the joints, as they are already parented in the order of cmds.joint calls. Here is a note from documentation "In the creation mode, a new joint will be created as a child of a selected transform or starts a hierarchy by itself if no transform is selected." if you don't want such behaviour, you should clear the selection
cmds.window('window1',menuBar=1) have to be always called, not inside the existance window condition, otherwise the UI elements will be attached to the script editor window
here is an updated script
from maya import cmds
global _endOutLoc
global _startOutLoc
global _rootLoc
def proxySkel (self):
global _endOutLoc, _startOutLoc, _rootLoc
target = cmds.ls (selection = True)
DDD = cmds.textField (textNam,
query = True,
text = True)
# CREATE THE LOCATOR
_endOutLoc = cmds.spaceLocator (position = (0, 0, 0), name = DDD + '_locEndOut')
_startOutLoc = cmds.spaceLocator (position = (0, 0, 0), name = DDD + '_locStartOut')
_rootLoc = cmds.spaceLocator (position = (0, 0, 0), name = DDD + '_locRoot')
# MOVE END LOCATOR IN SPACE
cmds.move (5, 0, 3, _endOutLoc, absolute = True)
cmds.move (0, 0, 3, _startOutLoc, absolute = True)
return _endOutLoc, _startOutLoc, _rootLoc
def jointsCreate (self):
global _endOutLoc, _startOutLoc, _rootLoc
if None in [_endOutLoc, _startOutLoc, _rootLoc]:
print('locators are not created yet')
return
target = cmds.ls (selection = True)
DDD = cmds.textField (textNam,
query = True,
text = True)
# CREATE THE JOINTS
rootJnt = cmds.joint (position = (0.0, 0.0, 0.0), name = _rootLoc[0] + '_jnt')
endOutJnt = cmds.joint (position = (0.0, 0.0, 0.0), name = _endOutLoc[0] + '_jnt')
startOutJnt = cmds.joint (position = (0.0, 0.0, 0.0), name = _startOutLoc[0] + '_jnt')
# PLACE THE JOINTS INTO SPACE
rootConst = cmds.parentConstraint (_rootLoc, rootJnt, mo = False)
endOutConst = cmds.parentConstraint (_endOutLoc, endOutJnt, mo = False)
startInConst = cmds.parentConstraint (_startOutLoc, startOutJnt, mo = False)
# DELETE CONSTRAINTS AFTER ALIGNMENT
cmds.delete (rootConst, endOutConst, startInConst)
# CREATE THE JOINT HIERARCHY
#cmds.parent (endOutJnt, rootJnt)
#cmds.parent (startOutJnt, endOutJnt)
if(cmds.window('window1',q=1,ex=1)):
cmds.deleteUI('window1')
cmds.window('window1',menuBar=1)
cmds.columnLayout()
textNam = cmds.textField(width=150,
text='Name',
backgroundColor=[0.6233005264362554, 1.0, 0.9765011062790875])
cmds.separator()
cmds.rowLayout(numberOfColumns=3)
cmds.button(width=65,
command = proxySkel,
backgroundColor=[0.0, 0.2187533379110399, 1.0],
label='Locators')
cmds.separator(style='none',
width=3)
cmds.button(width=78,
command = jointsCreate,
backgroundColor=[0.7971007858396277, 0.0, 0.0],
label='Joints')
cmds.showWindow('window1')
I generate the 4x4 transformation matrices over time for each object in a scene and use the VectorKeyframeTrack to set the transform matrix on a Mesh object. I am able to animate the objects individually with an AnimateAction for each object but cannot figure out how to have all objects animate simultaneously with a single .play() call and keep them in sync. This is as far as I've gotten, hoping that starting with the second loop the objects would be time synchronized, but they aren't:
import pythreejs as pjs
rod_mesh = pjs.Mesh(
pjs.CylinderBufferGeometry(0.005, 0.005, sys.constants[lB] - sys.constants[h] / 2,),
pjs.MeshStandardMaterial(color='red')
)
plate_mesh = pjs.Mesh(pjs.PlaneBufferGeometry(sys.constants[h], sys.constants[w]),
pjs.MeshStandardMaterial(color='blue', side='DoubleSide'))
# Animation will not update without this set.
rod_mesh.matrixAutoUpdate = False
plate_mesh.matrixAutoUpdate = False
# Set initial position/orientation
rod_mesh.matrix = rod_matrices[0]
plate_mesh.matrix = plate_matrices[0]
# Setup scene
view_width = 600
view_height = 400
camera = pjs.PerspectiveCamera(position=[0.25, 0.25, 0.25], aspect=view_width/view_height)
key_light = pjs.DirectionalLight(position=[0, 10, 10])
ambient_light = pjs.AmbientLight()
scene_pjs = pjs.Scene(children=[rod_mesh, plate_mesh, camera, key_light, ambient_light])
controller = pjs.OrbitControls(controlling=camera)
renderer = pjs.Renderer(camera=camera, scene=scene_pjs, controls=[controller], width=view_width, height=view_height)
# Specify KeyframeTracks
rod_track = pjs.VectorKeyframeTrack(name='.matrix', times=list(sys.times), values=rod_matrices)
plate_track = pjs.VectorKeyframeTrack(name='.matrix', times=list(sys.times), values=plate_matrices)
rod_clip = pjs.AnimationClip(tracks=[rod_track])
plate_clip = pjs.AnimationClip(tracks=[plate_track])
rod_mixer = pjs.AnimationMixer(rod_mesh)
plate_mixer = pjs.AnimationMixer(plate_mesh)
rod_action = pjs.AnimationAction(rod_mixer, rod_clip, rod_mesh)
plate_action = pjs.AnimationAction(plate_mixer, plate_clip, plate_mesh)
# Try to enforce syncronization among actions at each loop start
plate_action.exec_three_obj_method('syncWith', 'IPY_MODEL_' + rod_action.get_view_spec()['model_id'])
rod_action.exec_three_obj_method('syncWith', 'IPY_MODEL_' + plate_action.get_view_spec()['model_id'])
listener_func = '() => {{ {}.syncWith({}); }}'.format('IPY_MODEL_' + plate_action.get_view_spec()['model_id'], 'IPY_MODEL_' + rod_action.get_view_spec()['model_id'])
rod_mixer.exec_three_obj_method('addEventListener', 'loop', listener_func)
syncWith() must need to be called at every frame transition but I'm not sure how to affect the animation frame loop from pythreejs.
A solution was given here:
https://github.com/jupyter-widgets/pythreejs/issues/262
The key is to animate the scene instead of the individual meshes and the trick to do so is to name the meshes and then use scene/<mesh name>.<attribute to change> when setting up the KeyFrameTracks. Here is my example that was reworked:
rod_mesh = pjs.Mesh(pjs.CylinderBufferGeometry(0.005, 0.005, sys.constants[lB] - sys.constants[h] / 2),
pjs.MeshStandardMaterial(color='red'),
name='rod' # name each mesh!
)
plate_mesh = pjs.Mesh(pjs.PlaneBufferGeometry(sys.constants[h], sys.constants[w]),
pjs.MeshStandardMaterial(color='blue', side='DoubleSide'),
name="plate" # name each mesh!
)
# For updating the transform matrices directly set:
rod_mesh.matrixAutoUpdate = False
plate_mesh.matrixAutoUpdate = False
# Scene setup
view_width = 600
view_height = 400
camera = pjs.PerspectiveCamera(position=[0.25, 0.25, 0.25], aspect=view_width/view_height)
key_light = pjs.DirectionalLight(position=[0, 10, 10])
ambient_light = pjs.AmbientLight()
scene_pjs = pjs.Scene(children=[rod_mesh, plate_mesh, camera, key_light, ambient_light])
controller = pjs.OrbitControls(controlling=camera)
renderer = pjs.Renderer(camera=camera, scene=scene_pjs, controls=[controller], width=view_width, height=view_height)
# Key thing here is to set the attribute you want to change as a sub-item of the scene. Use the names of the meshes above.
rod_track = pjs.VectorKeyframeTrack(name='scene/rod.matrix',
times=list(sys.times),
values=rod_matrices)
plate_track = pjs.VectorKeyframeTrack(name='scene/plate.matrix',
times=list(sys.times),
values=plate_matrices)
# Now create a single clip with both tracks and animate the scene:
clip = pjs.AnimationClip(tracks=[rod_track, plate_track], duration=sys.times[-1])
action = pjs.AnimationAction(pjs.AnimationMixer(scene_pjs), clip, scene_pjs)
Here is my fully working example:
https://gist.github.com/moorepants/c5ebb846499c4002744b8c101705015f
I want to use a checkbox to control the ratio multiplied in slider function.
First I try to change the variable directly, but failed.
Then I try to change the dragCommand, but also failed.
How can I control it?
import pymel.core as pm
import math
myRatio = math.sqrt(2) * 0.5
def myPolyBevel(*args):
# called by convert
def convertOn(*args):
#myRatio = math.sqrt(2) * 0.5
myOffsetSlider.dragCommand = myOffsetOn
def convertOff(*args):
#myRatio = 1.0
myOffsetSlider.dragCommand = myOffsetOff
# called by offset
def myOffsetOn(*args):
temp = pm.floatSliderGrp( myOffsetSlider, query = True, value = True ) * myRatio
pm.setAttr( myBevel.name()+".offset", temp )
def myOffsetOff(*args):
temp = pm.floatSliderGrp( myOffsetSlider, query = True, value = True )
pm.setAttr( myBevel.name()+".offset", temp )
# main
if pm.selected():
# add Bevel
newBevel = pm.polyBevel3( pm.selected(), offset = 0.1 * myRatio, segments = 2, smoothingAngle = 30, chamfer = 1 )
myBevel = newBevel[0]
# UI
bevelWindow = pm.window(title = 'Bevel')
bevelLayout = pm.columnLayout()
myConvert = pm.checkBoxGrp( numberOfCheckBoxes = 1, label = '', label1 = 'Convert', value1 = 1, onCommand = convertOn, offCommand = convertOff )
myOffsetSlider = pm.floatSliderGrp( label='Offset', field = True,
minValue = 0.0, maxValue = 5.0,
fieldMinValue = 0.0, fieldMaxValue = 100.0,
value = 0.1, step = 0.001,
dragCommand = myOffsetOn, changeCommand = myOffsetOn )
pm.showWindow()
# Main
mainWindow = pm.window(title = 'Star')
mainLayout = pm.gridLayout( cellWidthHeight = (40,40), numberOfColumns = 5 )
bevelButton = pm.button( label = 'Bevel', command = myPolyBevel)
pm.showWindow()
You may have to not nest all this command, it makes it harder (or use some Class method)
use partial to pass args :
Maya Python - Using data from UI
here a useful post you can refer, check theodor and my answers on the topic (we often answer this question )
I am trying to implement the code on this website to estimate what value of K I should use for my K means clustering.
https://datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-reloaded/
However I am not getting any success - in particular I am trying to get the f(k) vs the number of clusters k graph which I can use to procure the ideal value of k to use.
My data format is as follows:
Each of the coordinates have 5 dimensions/variables i.e. they are data points that live in a five-dimensional space.
The list of the coordinates are below, where for example the first data point has coordinates ( 35.38361202590826,-24.022420305129415, 0.9608968122051765, -11.700331772145386, -9.4393980963685).
Variable1 = [35.38361202590826, 3.0, 10.0, 10.04987562112089, 5.385164807134505, 24.35159132377184, 10.77032961426901, 10.816653826391967, 18.384776310850235, 14.317821063276353, 24.18677324489565, 3.0, 24.33105012119288, 8.94427190999916, 2.82842712474619, 4.123105625617661, 4.47213595499958, 13.453624047073712, 12.529964086141668, 19.4164878389476, 5.385164807134505, 5.0, 24.041630560342618, 30.083217912982647, 15.132745950421555, 1.414213562373095, 21.470910553583888, 12.649110640673516, 9.0, 9.055385138137416, 16.124515496597102, 18.027756377319946, 7.615773105863908, 4.47213595499958, 5.0, 16.124515496597102, 8.246211251235321, 3.0, 23.02172886644268, 2.23606797749979, 10.0, 13.416407864998737, 14.7648230602334, 12.649110640673516, 2.82842712474619, 9.899494936611665, 12.806248474865697, 13.0, 10.19803902718557, 10.440306508910549]
Variable2 = [-24.022420305129415, -40.0, -21.0, -36.020346285601605, -14.298541039632994, -10.225204451297113, -7.242118188905023, -10.816653826391967, -16.263455967290593, -0.9079593845004517, -5.70559779110359, -1.0, -17.426292654367874, -0.4472135954999579, -12.727922061357855, -38.32062875574061, -15.205262246998569, -13.89960053482201, -6.943355894868313, -18.43793805396085, -14.298541039632994, -8.0, -9.899494936611665, -10.537436550735357, -9.251460406371256, -1.414213562373095, -0.23287321641631115, -4.743416490252569, -10.0, -25.951408627588936, -5.457528321925173, -11.648704120729812, -15.231546211727816, -9.838699100999074, -2.2, 4.713319914389921, -3.395498750508662, -32.0, -16.59301967354925, -4.47213595499958, -3.4, -13.416407864998737, 4.944183868793753, -3.478505426185217, -21.213203435596423, -18.384776310850235, -6.871645523098667, -21.0, -5.491251783869154, -8.620436566990362]
Variable3 = [0.9608968122051765, 22.0, 21.0, 18.507691737905798, 15.412713068695306, -8.08982038917884, -0.7427813527082074, -7.211102550927978, -14.849242404917499, -0.4190581774617469, -10.170848236315095, -7.0, 1.150792911137501, -5.366563145999495, -12.727922061357855, 4.85071250072666, 9.838699100999074, -8.473553267217696, 6.065460321953928, -10.249021432229634, 4.642383454426297, -9.0, 9.899494936611665, 4.354587344310195, -8.854969246098202, -8.48528137423857, -10.292996165600954, -11.067971810589327, -30.0, -10.932721081409808, -14.6360986815266, -22.188007849009164, 0.0, -7.155417527999327, -5.4, -12.279438724331637, 19.40285000290664, -7.0, 18.938629784469825, 8.94427190999916, 3.8, -8.94427190999916, -43.549455173073746, -8.538149682454623, -11.31370849898476, 1.4142135623730951, -10.619815808425212, 12.0, 7.060180864974626, -7.854175538813441]
Variable4 = [-11.700331772145386, -8.0, -5.0, -2.9851115706299676, -10.398938937914904, -8.459406092237773, -7.242118188905023, -10.539303728279352, -21.920310216782973, -8.03194840135015, -10.791021909261136, -10.0, -9.69954025101608, -2.6832815729997477, -23.33452377915607, -7.761140001162655, -17.44133022449836, -4.980070779856015, -2.7134954071899156, -6.48933015307002, -12.441587657862476, -5.2, -18.384776310850235, -10.603918800266811, -14.604091070057484, -4.949747468305833, -1.3506646552146047, -7.905694150420948, -14.0, -29.706080514133717, -2.4806946917841692, -23.574758339572238, -3.2826608214930637, -5.813776741499453, -13.4, -4.9613893835683385, -11.884245626780316, -19.0, -5.473090258814675, -2.23606797749979, -2.0, -2.6832815729997477, -6.163297699455227, -12.01665510863984, -12.727922061357855, -12.020815280171307, -8.589556903873333, -18.53846153846154, -5.491251783869154, -4.789131426105757]
Variable5 = [-9.4393980963685, -4.0, -2.0, -0.29851115706299675, -9.84185292338375, 6.118696639531204, -6.127946159842712, -2.218800784900916, 10.606601717798213, 0.6984302957695782, 0.7442084075352507, -0.0, 3.452378733412503, 1.3416407864998738, -6.363961030678928, 6.305926250944657, -5.813776741499453, -0.4459764877482998, -0.7980868844676221, 7.673890419106611, -1.4855627054164149, 1.4, -2.8284271247461903, -2.925218979383948, 3.9649116027305387, 0.7071067811865475, 0.4191717895493601, 1.5811388300841895, -4.0, 4.748555621218401, 4.341215710622296, 4.714951667914447, -5.120950881529179, 4.919349550499537, 6.2, 0.6201736729460423, -6.305926250944657, -9.0, -6.168085847235585, 0.0, -1.0, 1.3416407864998738, 3.3186987612451224, 4.427188724235731, 4.242640687119285, 4.949747468305833, 5.9346029517670305, 2.3076923076923075, -3.1378581622109447, 1.436739427831727]
I am able to use scikit-learn to create clusters with these coordinates however I am interested in finding the optimal k value to use - however scikit-learn does not have a feature where I can estimate the optimal value of K with this technique (or any technique as far as I am aware).
You can try the code in the last comment by Monte Shaffer.
Here's a simplified version:
import numpy as np
import random
from numpy import zeros
class KMeansFK():
def __init__(self, K, X):
self.K = K
self.X = X
self.N = len(X)
self.mu = None
self.clusters = None
self.method = None
def _cluster_points(self):
mu = self.mu
clusters = {}
for x in self.X:
bestmukey = min([(i[0], np.linalg.norm(x-mu[i[0]])) \
for i in enumerate(mu)], key=lambda t:t[1])[0]
try:
clusters[bestmukey].append(x)
except KeyError:
clusters[bestmukey] = [x]
self.clusters = clusters
def _reevaluate_centers(self):
clusters = self.clusters
newmu = []
keys = sorted(self.clusters.keys())
for k in keys:
newmu.append(np.mean(clusters[k], axis = 0))
self.mu = newmu
def _has_converged(self):
K = len(self.oldmu)
return(set([tuple(a) for a in self.mu]) == \
set([tuple(a) for a in self.oldmu])\
and len(set([tuple(a) for a in self.mu])) == K)
def find_centers(self, K, method='random'):
self.method = method
X = self.X
K = self.K
# https://stackoverflow.com/questions/44372231/population-must-be-a-sequence-or-set-for-dicts-use-listd
self.oldmu = random.sample(list(X), K)
if method != '++':
# Initialize to K random centers
self.mu = random.sample(list(X), K)
while not self._has_converged():
self.oldmu = self.mu
# Assign all points in X to clusters
self._cluster_points()
# Reevaluate centers
self._reevaluate_centers()
def _dist_from_centers(self):
cent = self.mu
X = self.X
D2 = np.array([min([np.linalg.norm(x-c)**2 for c in cent]) for x in X])
self.D2 = D2
def _choose_next_center(self):
self.probs = self.D2/self.D2.sum()
self.cumprobs = self.probs.cumsum()
r = random.random()
ind = np.where(self.cumprobs >= r)[0][0]
return(self.X[ind])
def init_centers(self,K):
self.K = K
#self.mu = random.sample(self.X, 1)
self.mu = random.sample(list(self.X), 1)
while len(self.mu) < self.K:
self._dist_from_centers()
self.mu.append(self._choose_next_center())
def get_ak(self,k, Nd):
if k == 2:
return( 1 - 3.0 / (4.0 * Nd ) )
else:
previous_a = self.get_ak(k-1, Nd)
return ( previous_a + (1.0-previous_a)/6.0 )
def fK(self, thisk, Skm1=0):
X = self.X
Nd = len(X[0])
self.find_centers(thisk, method='++')
mu, clusters = self.mu, self.clusters
Sk = sum([np.linalg.norm(mu[i]-c)**2 \
for i in range(thisk) for c in clusters[i]])
if thisk == 1:
fs = 1
elif Skm1 == 0:
fs = 1
else:
fs = Sk/(self.get_ak(thisk,Nd)*Skm1)
return fs, Sk
def run(self, maxk):
ks = range(1,maxk)
fs = zeros(len(ks))
Wks,Wkbs,sks = zeros(len(ks)+1),zeros(len(ks)+1),zeros(len(ks)+1)
# Special case K=1
self.init_centers(1)
fs[0], Sk = self.fK(1)
# Rest of Ks
for k in ks[1:]:
self.init_centers(k)
fs[k-1], Sk = self.fK(k, Skm1=Sk)
self.fs = fs
And then run it on your data:
X = np.array([Variable1, Variable2, Variable3, Variable4, Variable5])
km = kmeans.KMeansFK(2, X)
km.run(5)
Now km.clusters has the result.
I have multiple lines plots that are plotted on the same axes in Matplotlib. I'm trying to use the Slider widget to adjust the lines, but for some reason only the first line plot is showing, and nothing is updated when I move the 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()
If you remove the lines between plotGraph() and p.show() you can see the original plots.
To be honest, you made a little mess with the axis positioning and on the update function. I took the liberty to write again the plotting part and put the comment in there:
# 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()
By the way, if you want to simulate an damped oscillation, I strongly suggest you to give a look to the integrate module of scipy, wich contain the odeint function to integrate differential equation in a better way than what are you doing (that is called Euler integration, and is really error-prone)