[SOLVED] HELP: What could be a very Simple question on OnUpdate() function

I pass the following to a function that is not behaving as I want. It could be something simple but yet I can’t get it. It’s becoming very frustrating!!!



Passed parameters:

maxSpeed = 1.3

acceleration = 1.0;

initial speed v0 is 0.0;

startPosition is the initial position of spatial at (0,0,0)

endPosition is the destination at (0.737, 0.414, 0.0)



(of course we all know v = v0 + at >>>> basing my logic on this formula)



Given an OnUpdate() function like this:



[java]

@Override

public void onUpdate(float tpf) {



if (spatial != null)

{

if(acceleration > epsilon)

{

speed += tpf * acceleration;

System.out.println("Accelerated Speed: "+speed);



// if final speed exceeds max speed

if( speed > maxSpeed )

{

speed = maxSpeed;

}



}



if (spatial != null) {

Vector3f dir = endPosition.subtract( startPosition );

dir.normalize();

Vector3f velocity = dir.mult( speed * tpf );

Vector3f pos = spatial.getLocalTranslation();

spatial.setLocalTranslation( pos.add(velocity) );

}

[/java]



debugging result in a final Accelerated Speed: 1.149799 (should be 1.3) and spatial Position: (0.48012716, 0.26970512, 0.0) should be (0.737, 0.414, 0.0)



anyone can explain what am I doing wrong??

im not sure how you are ending the app, but that might just be your issue… since all the values indicate you where going on the right path but ended before reaching destination… the final accelerated speed could either way not match the max speed, simply cuz it wasnt given enough time to accelerate to max speed…



hope this helps… cheers…

thanks dixel, actually it does reach the max speed - which is the strangest part of this question :S

You are right about the velocity formula but you’re not applying it correctly to get the position. Position is the integral over velocity. You’re just multiplying time delta with speed instead of integrating. All you get is an approximation (that’s why you get lower values then expected).

Thanks androlo… could you please explain it more? I looked up this article and tried to use the function from it:



http://www.ugrad.math.ubc.ca/coursedoc/math101/notes/applications/velocity.html



should I change the velocity function?



[java]Vector3f velocity = dir.mult( startPosition + previousSpeed * time + (acceleration* time^2)/2 );[/java]



could you please explain more?

Yes but skip the startPosition term in that formula because you’re already there.





Vector3f pos = spatial.getLocalTranslation();

spatial.setLocalTranslation( pos.add(velocity) ); ← already there.



Just use the code you got, but add that quadratic term at the end. It should work.





Vector3f velocity = dir.mult( speed * tpf + accelerationtpftpf*0.5f );





The starting-point for your loop (0,0,0) is only relevant in the first update, since you’re re-iterating the formula every time. The next update your starting point will be the value you calculated in the previous one etc.

1 Like

First, thank you for taking the time to answer me.



If I understood you correctly this is the updated method (by skipping x(0):



[java]

// the exact current position is x(t) = x(0) + v(0)*t + 1/2(at^2)

// which is the integral of the current speed - previousPosition

if (spatial != null) {



Vector3f dir = endPosition.subtract( startPosition );

dir.normalize();

//Vector3f velocity = dir.mult(currentSpeed * tpf );

Vector3f velocity = dir.mult( currentSpeed * tpf + acceleration *tpf * tpf * 0.5f );

Vector3f pos = spatial.getLocalTranslation();

spatial.setLocalTranslation( pos.add(velocity) );

}[/java]



We’re getting there as the updated speed increased with the time perfectly.

However, given an acceleration of 1m/s and a duration of 1.3s , the spatial is still not perfectly aligned with the destination. See output below:



[java]

Accelerated Speed: 1.266547

time: 1.266535

Final SPEED: 1.266547

>>>>>>>>> Spatial Current Position is >>>>>>>>>>>>>: (0.19487609, 0.64878494, 0.0)

>>>>>>>>> Spatial Destination is >>>>>>>>>>>>>: (0.243, 0.809, 0.0)

Accelerated Speed: 1.283226

time: 1.2832737

Final SPEED: 1.283226

>>>>>>>>> Spatial Current Position is >>>>>>>>>>>>>: (0.20003241, 0.66595143, 0.0)

>>>>>>>>> Spatial Destination is >>>>>>>>>>>>>: (0.243, 0.809, 0.0)

Accelerated Speed: 1.2999384

time: 1.2999259

Final SPEED: 1.2999384

>>>>>>>>> Spatial Current Position is >>>>>>>>>>>>>: (0.20526715, 0.683379, 0.0)

>>>>>>>>> Spatial Destination is >>>>>>>>>>>>>: (0.243, 0.809, 0.0)

Accelerated Speed: 1.3165154

time: 1.3165054

Final SPEED: 1.3

>>>>>>>>> Spatial Current Position is >>>>>>>>>>>>>: (0.21058029, 0.70106757, 0.0) <<<<<<<<<

>>>>>>>>> Spatial Destination is >>>>>>>>>>>>>: (0.243, 0.809, 0.0)[/java] <<<<<<<<<



here’s the whole function to be on the same page:

[java]

public class AccelerateTrack extends AbstractCinematicEvent {



private static final Logger log = Logger.getLogger(AccelerateTrack.class.getName());

private Vector3f startPosition;

private Vector3f endPosition;

private Spatial spatial;

private String spatialName = “”;

private float value = 0;

private float maxSpeed;

private float currentSpeed;

private float acceleration;

private float previousSpeed;

// private float accelerationFactor = 0.4f; // not used

// private float decelerationFactor = -0.04f;

float epsilon = 0.001f; // used to compare floats accurately



// create an instance of the Simpleapplication inside Jme3Cinematics

private Jme3Cinematics myApp = Jme3Cinematics.getApp();



// reads the asset manager initialized in Jme3Cinematics

private AssetManager assetManager = myApp.getAssetManager();





public AccelerateTrack(Spatial spatial, Vector3f endPosition) {

this.endPosition = endPosition;

this.spatial = spatial;

spatialName = spatial.getName();

}







public AccelerateTrack(Spatial spatial, Vector3f endPosition, float initialDuration,

float acceleration, float previousSpeed, float maxSpeed,

LoopMode loopMode)

{

super(initialDuration, loopMode);

this.endPosition = endPosition;

this.spatial = spatial;

//this.accelerationFactor = accelerationFactor;

this.acceleration = acceleration;

this.maxSpeed = maxSpeed;

this.previousSpeed = previousSpeed;

this.spatialName = spatial.getName();

//speed = previousSpeed; // speed is a protected variable in cinemtics events (not used)

currentSpeed = previousSpeed; // speed is a protected variable in cinemtics events

}





@Override

public void initEvent(Application app, Cinematic cinematic) {

super.initEvent(app, cinematic);

if (spatial == null) {



spatial = cinematic.getScene().getChild(spatialName);

if (spatial == null) {

} else {

log.log(Level.WARNING, “spatial {0} not found in the scene”, spatialName);

}

}

}





@Override

public void onPause() {

// do nothing

}



@Override

public void onPlay() {

if (playState != playState.Paused) {

startPosition = spatial.getWorldTranslation().clone();

}

if (initialDuration == 0 && spatial != null) {



spatial.setLocalTranslation(endPosition);

}



}



@Override

public void onStop() {

value = 0;



}



// note that reverse here is done via acceleration, then deceleration

// and NOT deceleration than acceleration (like the sim)

@Override

public void onUpdate(float tpf) {



// to be synchronized with setTime()

if (spatial != null)

{

//value = Math.min(time / initialDuration, 1.0f);



// if positive acceleration

if(acceleration > epsilon)

{

currentSpeed += tpf * (acceleration * myApp.getAnimationSpeed());

//currentSpeed += time * accelerationFactor;





System.out.println("Accelerated Speed: "+currentSpeed);

System.out.println("Acceleration time: "+time);



// limit speed to a max speed

if( currentSpeed > maxSpeed * myApp.getAnimationSpeed() )

{

currentSpeed = maxSpeed * myApp.getAnimationSpeed();

}



}



// if negative acceleration (or deceleration)

else if(acceleration < -epsilon)

{

currentSpeed += tpf * (acceleration / myApp.getAnimationSpeed()); // we divide b/c deceleration is reduced (by nx) with faster animation

//currentSpeed += time * (decelerationFactor * myApp.getAnimationSpeed()); // this one works only for 1x >>> WEIRD





System.out.println("Reduced Speed: "+currentSpeed);

System.out.println("Deceleration Time: “+time);



// assuring vehicle stops completely when 0 speed is reached

if( currentSpeed < -epsilon )

{

currentSpeed = 0;

}

}



// TODO: might not be needed - implemented for vehicle going in reverse bug

else if( FastMath.abs(currentSpeed) < -epsilon )

{

currentSpeed = 0;

System.out.println(“FORCE STOP SPATIAL!”);

}



System.out.println(“Final SPEED: “+currentSpeed);

System.out.println(”>>>>>>>>> Spatial Position is >>>>>>>>>>>>>: " +spatial.getLocalTranslation());

System.out.println(”>>>>>>>>> Spatial Destination is >>>>>>>>>>>>>: " +endPosition);

//System.out.println(”>>>>>>>>> Spatial Start Position is >>>>>>>>>>>>>: " +startPosition);

}



// the exact current position is x(t) = x(0) + v(0)*t + 1/2(at^2)

// which is the integral of the current speed - previousPosition

if (spatial != null) {



Vector3f dir = endPosition.subtract( startPosition );

dir.normalize();

//Vector3f velocity = dir.mult(currentSpeed * tpf );

Vector3f velocity = dir.mult( currentSpeed * tpf + acceleration *tpf * tpf * 0.5f );

Vector3f pos = spatial.getLocalTranslation();

spatial.setLocalTranslation( pos.add(velocity) );





}

}





@Override

public void write(JmeExporter ex) throws IOException {

super.write(ex);

OutputCapsule oc = ex.getCapsule(this);

oc.write(spatialName, “spatialName”, “”);

oc.write(endPosition, “endPosition”, null);

}



@Override

public void read(JmeImporter im) throws IOException {

super.read(im);

InputCapsule ic = im.getCapsule(this);

spatialName = ic.readString(“spatialName”, “”);

endPosition = (Vector3f) ic.readSavable(“endPosition”, null);

}

}



[/java]

Seems you’re adding weird factors to the acceleration without compensating for it in the velocity formula. Also I’m not sure it really is linear acceleration with all that animation and sign-shifting stuff going on. If that’s the case then the position/velocity formulas won’t work.

1 Like

Well it is accurate enough for the purpose of my project. Major improvement from my previous code so good job pointing it out.



Again thank you so much for taking the time and looking at it.