![]() |
#1
|
|||
|
|||
RE:Slide Joints and physics optimization
Hi,
I have constructed a virtual environment containing, amongst other things, a forklift. As the "name of the game" for this project was realism I have constructed the truck using purely physics joints. This works well, the truck follows the lay of the land and behaves pretty well how i want it to. However, one of the tasks for the user is to load some items (steel cages) onto the back of a lorry, at this point things go a bit weird. I am using a slide joint for the forks and 'applyForce' on joystick button events (within a timer) to raise and lower them, but when I pick up the cages they bounce and jump all over the place - not good. ![]() ![]() Is applyForce the best way to operate this type of slide joint, or is having it within a timer making the forks movement jumpy???? HELP, i've run out of ideas and this has to be finished by beginning of next week!! ![]() This is the code for the cages: Code:
top =cage1.collideBox(node = 'Cage_Top',bounce=0,density=.1) top.setFriction(80) bottom = cage1.collideBox(node = 'Cage_Bottom',bounce=0,density=.4) bottom.setFriction(80) side1=cage1.collideBox(node='Left_Ones',bounce=0,density=0.05) side2=cage1.collideBox(node='Right_Ones',bounce=0,density=0.05) cage1.enable(viz.COLLIDE_NOTIFY) Code:
#Build FLT# ########### flt = viz.add('flt8.ive') body = flt.getChild('Body') body.playsound('CE2a.WAV',viz.LOOP) body.collideBox(bounce=0, density = 1.25) lever1=flt.getChild('Lever1') lever1.collideBox(bounce=0,density=0.05) lever2=flt.getChild('Lever02') lever2.collideBox(bounce=0,density=0.05) #Get and process children run = flt.getChild('Shaft') run.collideBox(bounce=0, density = 0.1) run.setPosition([0.0,0.2,0.0]) print run.getPosition() guard = flt.getChild('ForkGuard') guard.translate([0,0,0.005]) guard.collideBox(bounce=0,density=0.05) fork1 = flt.getChild('Blades') #fork1.setPosition(0,-0.1,0) forks = fork1.collideBox(bounce=0,density = 0.1) forks.setFriction(200) steering = flt.getChild('Steering_Wheel') steerBox = steering.collideSphere(bounce=0,density=0.01) #Link bodyLink = viz.link(body,view,dstFlag=viz.LINK_BODY) bodyLink.preTrans([0,-0.12,0.28]) ##--MOTORS & JOINTS--## steerlink = viz.phys.addHingeJoint(body,steering,pos=[-0.005,1.153,0.813],axis0=[0,1,0]) steerlink.setMotorAngle(0,0,1,.25) #lever1link = viz.phys.addHingeJoint(body,lever1,pos=[0.249,0.763,0.993],axis0=[1,0,0]) lever1link=viz.phys.addFixedJoint(body,lever1) lever2link=viz.phys.addFixedJoint(body,lever2) #lever1link.setMotorAngle(0,0,100,.5) slideJoint = viz.phys.addSliderJoint(fork1,run,pos=[-0.005,0.5,1.317],axis0=(0,1,0)) slideJoint.setAxisFriction(0,12) slideJoint.setAxisLimit(0,-0.2,2.8) # Limit sliding distance guardJoint = viz.phys.addFixedJoint(guard,fork1) #cwLink = viz.phys.addFixedJoint(cw,body) #runJoint = viz.phys.addFixedJoint(run,body) runJoint = viz.phys.addHingeJoint(run,body,pos=[-0.005,0.279,1.21],axis0=[1,0,0]) #runJoint.setAxisFriction(0,10) #runJoint.setAxisLimit(0,-5,8) runJoint.setMotorAngle(0,-1,26,1) fr = viz.add('F_wheel1.ive',scale = [1,1,1],pos=[0.58,0.194,0.9]) fright = fr.collideSphere(bounce = 0, density = 1) fright.setFriction(5) frJoint = viz.phys.addHingeJoint(body,fr,pos=[0.58,0.194,0.9],axis0=(-1,0,0)) frJoint.setAxisFriction(0,1.5) fl = viz.add('F_wheel1.ive',scale = [1,1,1],pos=[-0.58,0.194,0.9]) fleft = fl.collideSphere(bounce = 0, density =1) fleft.setFriction(5) flJoint = viz.phys.addHingeJoint(body,fl,pos=[-0.58,0.194,0.9],axis0=(-1,0,0)) flJoint.setAxisFriction(0,1.5) rr = viz.add('F_wheel1.ive',scale=[1,1,1],pos=[0.0,0.194,-0.727]) #rr.playsound('CE2a.WAV',viz.LOOP) rearr = rr.collideSphere(bounce = 0, density = 3) rearr.setFriction(2) rrJoint = viz.phys.addWheelJoint(body,rr,pos=[0.0,0.194,-0.727],axis0=(0,1,0),axis1=(1,0,0)) rrJoint.setAxisBounce(0,0) rrJoint.setAxisBounce(1,0) rrJoint.setAxisFriction(1,.75) print rrJoint.getPosition() def steer(val): rrJoint.setMotorAngle(0,val,0xFF,.05) def steerWheel(val): steerlink.setMotorAngle(0,val,3,.1) def SetThrottle(val): rrJoint.setMotorThrottle(1,-val,9,1100) #Control Forks# def buttonTimer(): if joy.isButtonDown (7): print "Button is 7 down" fork1.applyForce([0,215,0]) elif joy.isButtonDown (8): print "Button 8 is down" fork1.applyForce ([0,-205,0]) if joy.isButtonDown (5): runJoint.setMotorAngle(0,-6,6,.03) elif joy.isButtonDown (6): runJoint.setMotorAngle(0,2,6,.03) vizact.ontimer(viz.FASTEST_EXPIRATION,buttonTimer) Cheers, Nige |
#2
|
|||
|
|||
I've created a sample script that creates a slider joint and uses the arrow keys to manually adjust the distance between the joint. Have a look at the SliderMotor class I made. It will update the motor velocity of the joint every frame to keep it at the desired distance. You can tweak the maxTorque and speed variables to control how quickly the it will go to the desired distance. This should be the most stable way of manually controlling a slider joint.
Code:
import viz viz.go() viz.clearcolor(viz.GRAY) #Enable physics viz.phys.enable() #Add ground plane ground = viz.add('tut_ground.wrl') ground.collidePlane() #Add 2 balls ball1 = viz.add('box.wrl',pos=(0,2.8,6)) ball1.collideSphere() ball2 = viz.add('ball.wrl',pos=(0,1.8,6)) ball2.collideSphere() ANCHOR_POS = (0,1.8,5) #Add a joint joint = viz.phys.addSliderJoint(ball1,ball2,pos=ANCHOR_POS,axis0=(0,1,0)) joint.setAxisLimit(0,-0.5,0.5) #Class that will force slider joint to specified distance class SliderMotor(viz.EventClass): def __init__(self,joint,maxTorque=40.0,speed=20.0): viz.EventClass.__init__(self) self.distance = 0.0 self.maxTorque = maxTorque self.speed = speed self.joint = joint self.callback(viz.TIMER_EVENT,self.onTimer) self.starttimer(0,0,viz.FOREVER) #Account for bug in current version of Vizard if viz.compareVersion('3.00.2708') >= 0: self.factor = viz.RAD_TO_DEG else: self.factor = 1.0 def onTimer(self,num): vel = self.factor * self.speed * (self.distance - self.joint.getAxisDistance(0)) self.joint.setMotorVelocity(0, vel, self.maxTorque) motor = SliderMotor(joint) #Use arrow keys to adjust motor desired distance def IncrementAngle(inc): motor.distance += inc * viz.elapsed() print motor.distance vizact.whilekeydown(viz.KEY_UP,IncrementAngle,0.1) vizact.whilekeydown(viz.KEY_DOWN,IncrementAngle,-0.1) JointDistLabel = viz.addText('Joint Distance: 0.00',viz.ORTHO) JointDistLabel.fontSize(24) JointDistLabel.translate(10,10) def UpdateAxisInfo(): JointDistLabel.message('Joint Distance: %.2f' % (joint.getAxisDistance(0))) vizact.ontimer(0,UpdateAxisInfo) |
#3
|
|||
|
|||
![]() Haven't been around for a while - finishing final year work etc etc ![]() ![]() Cheers |
#4
|
|||
|
|||
![]() ![]() I have (fairly) successfully implemented yr slider motor class & it works great THANKS ![]() ![]() - How could I replace the keyboard control event for joystick buttons? I was using a timer to look for a joy.isButtonDown event but seem unable figure out a way of using this method with yr wonderful SliderMotor class! ![]() - When lowering the forks sometimes the item that I was carrying (cages or pallets) get 'stuck' in thin air and only drop if they get knocked by the forks ![]() ![]() Here is the code for the cages: Code:
top =cage1.collideBox(node = 'Cage_Top',bounce=0) top.setFriction(0.5) bottom = cage1.collideBox(node = 'Cage_Bottom',bounce=0) bottom.setFriction(0.5) side1=cage1.collideBox(node='Left_Ones',bounce=0) side2=cage1.collideBox(node='Right_Ones',bounce=0) cage1.enable(viz.COLLIDE_NOTIFY) The forklift is a purely physics based affair rather than being based upon animations or links (as I had already mentioned last yr ![]() Code:
fork1 = flt.getChild('Blades') forks = fork1.collideBox(bounce=0) fork1.enable(viz.COLLIDE_NOTIFY) forks.setFriction(1) Thanks in advance ![]() |
#5
|
|||
|
|||
Using a timer and joy.isButtonDown should work. Have you tried something like this.
Code:
def checkButtons(): if joy.isButtonDown(1): IncrementAngle(0.1) if joy.isButtonDown(2): IncrementAngle(-0.1) vizact.ontimer(0,checkButtons) |
![]() |
|
|