Suggestion: Local X,Y,Z option for certain python functions

You know these

applyImpulse(point, impulse)

getLinearVelocity()

getVelocity(point)

The only problem is these work with global coordinates and not an object’s local coordinates, it would be very useful if they could be used for an object’s local x,y,z axis as well, as well as making other functions that get the velocity on just 1 axis. LIke this.

applyImpulse(point, impulse, local)
getLinearVelocity(local)
getVelocity(point, local)
getVelocityX(local)
getvelocityY(local)
getVelocityZ(local)

All you would need to make the function work with local coordinates is type true where it says local.

you can multiply by the axis you want from the orientation matrix to get/set the local motion

lessee if I can do this off the top of my head:


def pythag(A):
     return sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]) #replace the 5 spaces in this line with a tab
speed=o.getLinearVelocity()

#organize orientation matrix into a more convenient form
XAxis=[o.getOrientation[0,0],o.getOrientation[1,0],o.getOrientation[2,0]]
YAxis=[o.getOrientation[0,1],o.getOrientation[1,1],o.getOrientation[2,1]]
ZAxis=[o.getOrientation[0,2],o.getOrientation[1,2],o.getOrientation[2,2]]

#get speed vectors along each local axis
XSpeed=[XAxis[0]*speed[0],XAxis[1]*speed[1],XAxis[2]*speed[2]]
YSpeed=[YAxis[0]*speed[0]YAxis[1]*speed[1],YAxis[2]*speed[2]]
ZSpeed=[ZAxis[0]*speed[0],ZAxis[1]*speed[1],ZAxis[2]*speed[2]]

#get local speed magnitudes
localSpeed=[pythag(XSpeed),pythag(YSpeed),pythag(ZSpeed)]

theoretically, if I’m not being retarded right now, this should spit out your object’s local speed in a few different formats (speed vectors along each axis, as well as their magnitudes- the naming should be clear enough). if it doesn’t work, or works wrong, tell me and I (or someone else) might be able to fix it… hopefully this at least will give you a starting point though.

yeah you can always figure stuff out using matrices… but for the rest of maths um deficient… it would be nice if there was an easier way… but thanks for the info!

Captain oblivion: your script gives me a syntax error, but I can’t seem to find it.

It’s on line 13 or something.

darnit, to test it I actually have to open blender… too… much… effort…
XP

[edit] well, it doesn’t return any errors any more, but I haven’t tested if it returns the correct numbers


from math import sqrt

def pythag(A):
    return sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]) #replace the 5 spaces in this line with a tab

g=GameLogic
c=g.getCurrentController()
o=c.getOwner()
speed=o.getLinearVelocity()

#organize orientation matrix into a more convenient form
XAxis=[o.getOrientation()[0][0],o.getOrientation()[1][0],o.getOrientation()[2][0]]
YAxis=[o.getOrientation()[0][1],o.getOrientation()[1][1],o.getOrientation()[2][1]]
ZAxis=[o.getOrientation()[0][2],o.getOrientation()[1][2],o.getOrientation()[2][2]]

#get speed vectors along each local axis
XSpeed=[XAxis[0]*speed[0],XAxis[1]*speed[1],XAxis[2]*speed[2]]
YSpeed=[YAxis[0]*speed[0],YAxis[1]*speed[1],YAxis[2]*speed[2]]
ZSpeed=[ZAxis[0]*speed[0],ZAxis[1]*speed[1],ZAxis[2]*speed[2]]

#get local speed magnitudes
localSpeed=[pythag(XSpeed),pythag(YSpeed),pythag(ZSpeed)]

[edit 2]
well, I tested it. the bad news is, it doesn’t return the right numbers (unless it’s snapped to 90 degree angles)
the worse news is I’m too burnt out to see what’s wrong, or have the energy to fix it.
the good news is… hm. well, there is no good news ^^

Okay, I set the properties to string and I get the results, any possibility the X, Y, and Z speed could be condensed down so it outputs just one float number for the X, Y, and Z axis.

Instead of…
XSpeed=1.26261819,2.9181716,0.00000123

Condense it to a more usable form like this which I can set a property to a float instead of a string
Xspeed=1.52739371

The reason I need this is so I can apply a backwards impulse to an object to stop it using applyImpulse(point,impulse) and set the variables for XSpeed and YSpeed where the X and Y values should go.

'kay, so here’s the deal. firstly, you should be able to get the single number speed (that is, a single float for each axis) by using localSlpeed ([0] for X, [1] for Y, [2] for Z)
unfortunately, it doesn’t seem to work as the script currently stands.

if you want to apply an impulse to stop your object, shouldn’t you just apply -speed*mass? you don’t need local coordinates for that… unless I’m understanding wrong…

Okay, I got this

 
owner.applyImpulse( [pos,pos,pos],impulse)

Now I know I can add o. before the variable names and put it in the object’s property list to allow the object to work with the values, I for example do this.

 
owner.applyImpulse( [pos,pos,pos], [owner.XSpeed,owner.YSpeed,0])

And the object moves in a different direction when I press the brake button, but it isn’t quite the right direction, what variables and the various math involved would need to go in to make it quickly come to a stop regardless of direction?

I believe you’d do owner.applyImpulse([posX,posY,posZ],[-XSpeed,-YSpeed,0])
XSpeed and YSpeed are it’s speed this frame, in global coordinates. it seems a bit of a waste to store them as owner.XSpeed, because they will change every frame (you only need store in owner. if it needs to be accessed by another script, or in a later frame- if it’s used by one script during one frame, use a temporary variable)
if it’s mass is not 1, you need to multiply the speed by the mass.

basically, you get it’s speed, and apply force equal to it’s velocity but in the opposite direction. this will instantly stop it. if you want it to be more gradual, multiply the speeds by a number less than one.

Okay, so I have this all in one script


from math import sqrt
def pythag(A):
    return sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]) #replace the 5 spaces in this line with a tab
g=GameLogic
c=g.getCurrentController()
o=c.getOwner()
pos = o.getPosition()
speed=o.getLinearVelocity()
o.speeed=speed
#organize orientation matrix into a more convenient form
XAxis=[o.getOrientation()[0][0],o.getOrientation()[1][0],o.getOrientation()[2][0]]
YAxis=[o.getOrientation()[0][1],o.getOrientation()[1][1],o.getOrientation()[2][1]]
ZAxis=[o.getOrientation()[0][2],o.getOrientation()[1][2],o.getOrientation()[2][2]]
#get speed vectors along each local axis
XSpeed=[XAxis[0]*speed[0],XAxis[1]*speed[1],XAxis[2]*speed[2]]
YSpeed=[YAxis[0]*speed[0],YAxis[1]*speed[1],YAxis[2]*speed[2]]
ZSpeed=[ZAxis[0]*speed[0],ZAxis[1]*speed[1],ZAxis[2]*speed[2]]
#get local speed magnitudes
localSpeed=[pythag(XSpeed),pythag(YSpeed),pythag(ZSpeed)]
o.applyImpulse([pos,pos,pos],[XSpeed,YSpeed,0])

The only thing I added was the function at the end, when I press the brake button to execute this script my object always goes left (on global axis). Added a minus before the variables makes it not work as well as adding *mass after each variable

you don’t need any of the stuff to translate to local coordinates. it’s all redundant in this case, and as previously mentioned, doesn’t work anyways.

just use:


g=GameLogic
c=g.getCurrentController()
o=c.getOwner()

M=o.getMass()
speedX,speedY,speedZ=o.getLinearVelocity()

percent=.1

o.applyImpulse(o.getPosition(),[-speedX*percent*M,-speedY*percent*M,0])

if all is well, this should stop your object dead in it’s tracks. keep in mind that the script shouldn’t be always running, or your object won’t be able to move (unless you apply forces after the script, but then it’s just a waste of processor cycles, and kills momentum every frame)

what you were trying to do was to convert the velocity into local coordinates, then plug them into a formula that would have to convert them to global coordinates before applying the impulse, which is slightly redundant.

[edit]
tested and slightly changed code- if you want an instant stop, you can either remove all mention of the percent variable, or change it to 1. if you want a gradual stop, you can easily mess with the numbers 'till you get one you like (if it’s stopping too slowly, increase percent until it goes the speed you want, etc).

Ah, it works, thanks for all your help.

I also didn’t know you could have a list of three variables before that velocity function.

Hey, I’m new here. >>

Not sure what you’re trying to do, but to get localised velocity, you can do this:

  def getOrientedVelocity(object):
    v = object.getVelocity()
    o = object.getOrientation()
    vr =[0,0,0]
    vr[0] = v[0]*o[0][0] + v[1]*o[0][1] + v[2]*o[0][2]
    vr[1] = v[0]*o[1][0] + v[1]*o[1][1] + v[2]*o[1][2]
    vr[2] = v[0]*o[2][0] + v[1]*o[2][1] + v[2]*o[2][2]
    return vr

My own coding. Yes, I know it’s pointless to say that.