Sign in to follow this  

Steeering behaviours

This topic is 4198 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi. I'm having a little trouble with this simple task (ARGH). I'm trying to implement the basic steering behaviours of the agents. What I have is: the Seek behaiour: Vector3f Steering::Seek(Vector3f &targetPos, Agent* agent) { Vector3f desiredVelocity = targetPos - agent->GetWorldPosition(); desiredVelocity.Normalize(); desiredVelocity *= agent->GetMaxSpeed(); std::string str; SharedTools::VectorToString(desiredVelocity, str); FE_LOG("DesiredVelocity -> "+str); return desiredVelocity - agent->GetVelocity(); } Here is how I usse it: Update(double elapsedTime) { Vector3f steeringForce = Steering::Seek(m_pathToTravel.GetElementAt(m_pathToTravel.Size()-1), this); Vector3f accelaration = steeringForce / m_mass; m_velocity += accelaration * (float)elapsedTime; m_velocity.Truncate(m_maxSpeed); SetWorldPosition(GetWorldPosition() + (m_velocity * (float)elapsedTime)); } When I put the maxVelocity value to 1 this thing works properly, and when the value is less than 1 it works, but when I put 2 or 5 or something greater than that, the agent don't stop! It continues moving like there's no tomorrow! Any ideia suggestions???

Share this post


Link to post
Share on other sites
There is no MaxVelocity in your code. do you mean m_maxSpeed?

edit:

A suggestion:

It may be a good idea to ensure that desiredVelocity doesnt exceed (targetPos - agent->GetWorldPosition())
You want to seek the target, not double it ;)

[Edited by - Steadtler on June 16, 2006 2:47:01 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hi!

try not multiplying your accelaration by elapsedTime (only multiply in the position update).

Greetings!

Vicente

Share this post


Link to post
Share on other sites
I've Added the line:

steeringForce.Truncate(m_maxForce);

in the code:

Update(double elapsedTime)
{


Vector3f steeringForce = Steering::Seek(m_pathToTravel.GetElementAt(m_pathToTravel.Size()-1), this); //Arrive(m_pathToTravel.GetElementAt(m_pathToTravel.Size()-1), DEC_MEDIUM, this);

steeringForce.Truncate(m_maxForce);

Vector3f accelaration = steeringForce / m_mass;

m_velocity += accelaration * (float)elapsedTime;

m_velocity.Truncate(m_maxSpeed);

Vector3f newPos = GetWorldPosition() + (m_velocity * (float)elapsedTime);

//updating the rotation (heading)
SetLocalRotation(GetRotation(Vector3f(0,1,0), newPos - GetWorldPosition()));

SetWorldPosition(newPos);

}



And now it doesn't fly away. But in the beggining it starts to walk to the wrong direction and then it keeps ok with the normal behaviour. :S Damned!
What could it be now??? ARGH

Share this post


Link to post
Share on other sites
You're mixing mass/accel/force too much. I fixed some things in your code:


Vector3f Steering::Seek(Vector3f &targetPos, Agent* agent)
{
Vector3f desiredVelocity = targetPos - agent->GetWorldPosition();

desiredVelocity.Normalize();
// this seems not to be ok. reason: as we aproach the target, we will be unable
// to decelerate until we miss it at full speed. But maybe it's what you want here...
desiredVelocity *= agent->GetMaxSpeed();

// this returns difference of velocities, this is not "force"
return desiredVelocity - agent->GetVelocity();
}


Vector3f steeringVelDiff = Steering::Seek(m_pathToTravel.GetElementAt(m_pathToTravel.Size()-1), this);

// this is somewhat "around-the-globe", so I prefer using "maxAccel" instead of "maxForce".
Vector3f force = steeringVelDiff * m_mass;
force.Truncate(m_maxForce);
Vector3f acceleration = force / m_mass;

m_velocity += acceleration * (float)elapsedTime;
m_velocity.Truncate(m_maxSpeed);

Vector3f newPos = GetWorldPosition() + (m_velocity * (float)elapsedTime);

//updating the rotation (heading)
SetLocalRotation(GetRotation(Vector3f(0,1,0), newPos - GetWorldPosition()));

SetWorldPosition(newPos);
//[...]



But generally, it seems to be correct. Maybe it's your path that's calculated wrong (that can happen with grid-aligned paths, that a character wants to get to the center of current grid at first, instead of to the target).

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
You're mixing mass/accel/force too much. I fixed some things in your code:

*** Source Snippet Removed ***

But generally, it seems to be correct. Maybe it's your path that's calculated wrong (that can happen with grid-aligned paths, that a character wants to get to the center of current grid at first, instead of to the target).



Thanks a lot for the help!
But As I said before, now I get the desired behaviour except in the beggining.
When the agent starts to move, it wonders... It walks to the wrong side, then goes to the goal then start walking in the wrong direction, and then it goes to the target. And When I move the agent to another point, it behaves normally. Without running away from the target.
Seems theres some kind of numerical problem in the beggining! Could it be the elapsed time or something like that?

When I take off the elapsed time it gets really crazy and not working.

By the way, that line of code

steeringForce *= m_mass;



doesn't bring nothing new :S

Share this post


Link to post
Share on other sites
Quote:
Original post by gorogoro
When the agent starts to move, it wonders... It walks to the wrong side, then goes to the goal then start walking in the wrong direction, and then it goes to the target. And When I move the agent to another point, it behaves normally. Without running away from the target.


A couple comments:
1. Does the agent have a single goal the entire time (well, except when you change it by hand, of course), or is it following some spline-path? Try to make this as simple as spossible while still debugging.
2. Are you in possesion of a step-by-step debugger? Use it to find out what is happening in the beginning. That's what I did when I was writing my steering routines.
3. More debug output. I recommend (again!) using some kind of line-manager, that would display lines on the screen, that anybody can add anytime at runtime. You could then simply visualise your vectors.


Quote:
Original post by gorogoro
Seems theres some kind of numerical problem in the beggining! Could it be the elapsed time or something like that?


Who knows, you didn't show us where the elapsedTime comes from. Is it not negative (which sometimes happens with poorly-written timers)?

Quote:
Original post by gorogoro
By the way, that line of code
*** Source Snippet Removed ***

doesn't bring nothing new :S


Of course not, since:
1. It is not related to the problem.
2. Mass is most likely == 1, isn't it? (just guessing here[grin]).

But if you are introducing mass to the routine, at least do it right.

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Quote:
Original post by gorogoro
When the agent starts to move, it wonders... It walks to the wrong side, then goes to the goal then start walking in the wrong direction, and then it goes to the target. And When I move the agent to another point, it behaves normally. Without running away from the target.


A couple comments:
1. Does the agent have a single goal the entire time (well, except when you change it by hand, of course), or is it following some spline-path? Try to make this as simple as spossible while still debugging.
2. Are you in possesion of a step-by-step debugger? Use it to find out what is happening in the beginning. That's what I did when I was writing my steering routines.
3. More debug output. I recommend (again!) using some kind of line-manager, that would display lines on the screen, that anybody can add anytime at runtime. You could then simply visualise your vectors.


Quote:
Original post by gorogoro
Seems theres some kind of numerical problem in the beggining! Could it be the elapsed time or something like that?


Who knows, you didn't show us where the elapsedTime comes from. Is it not negative (which sometimes happens with poorly-written timers)?

Quote:
Original post by gorogoro
By the way, that line of code
*** Source Snippet Removed ***

doesn't bring nothing new :S


Of course not, since:
1. It is not related to the problem.
2. Mass is most likely == 1, isn't it? (just guessing here[grin]).

But if you are introducing mass to the routine, at least do it right.



I'm just testing this steering routine to implement the others! So the agent only have a goal. Steer to a point, nothing more :).

Yes, I've tried the step by step debug method, but it >censored< up the time variable.. So I'm printing out messages..

And yes, the mass is 1 :$

About the time I have no ideia how it is made. It was made by the dudes who are working in the rendering engine. I'm just the guy in the corner trying to make some AI for the game :S.

[Edited by - Timkin on June 19, 2006 9:13:17 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by gorogoro
Yes, I've tried the step by step debug method, but it >censored< up the time variable.. So I'm printing out messages..


Clamp the time difference in each loop from, say, 0 to 0.01 second. This will alow you to debug as well as remove any possible timer glitches.

[Edited by - Timkin on June 19, 2006 9:37:17 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Quote:
Original post by gorogoro
Yes, I've tried the step by step debug method, but it >censored< up the time variable.. So I'm printing out messages..


Clamp the time difference in each loop from, say, 0 to 0.01 second. This will alow you to debug as well as remove any possible timer glitches.


Here is a sample of the file debuging values of elapsedTime variable.


.07
.04
.0049
.0052





sometimes I get these huge values

.0046
.0066
.0049
.0051
.0048
.0047
.0047
.245630
.0073
.0062
.0056
.0054





or this:


.0087
.0081
.01
.01
.0096
.0066






So I changed the Update code to something like this:


void SpiderAgent::Update(double elapsedTime)
{
if(elapsedTime > 0.0099)
elapsedTime = 0.0065;

std::string text;
SharedTools::RealToString(elapsedTime, text);
text.append("\n");

file.Write(text);

Vector3f steeringForce = Steering::Seek(m_pathToTravel.GetElementAt(m_pathToTravel.Size()-1), this);

steeringForce.Truncate(m_maxForce);
Vector3f accelaration = steeringForce / m_mass;

m_velocity += accelaration * (float)elapsedTime;

m_velocity.Truncate(m_maxSpeed);

Vector3f newPos = GetWorldPosition() + (m_velocity * (float)elapsedTime);
//updating the rotation (heading)
SetLocalRotation(GetRotation(Vector3f(0,1,0), newPos - GetWorldPosition()));

SetWorldPosition(newPos);
}





But that if is really really ugly. And things are kept hard coded. :s
By the way with this if statment the thing works just fine.

[Edited by - Timkin on June 19, 2006 9:53:50 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by gorogoro
So I changed the Update code to something like this:

*** Source Snippet Removed ***
But that if is really really ugly. And things are kept hard coded. :s


I didn't mean to clamp it in here, but immediately when you're geting the value from the timer (possibly in the main loop). This kind of hardcoding is well known - it enforces slowdown of the gameplay when desired frame rate cannot be achieved.

Quote:
Original post by gorogoro
By the way with this if statment the thing works just fine.


Good for you!
Now go fix that mass/force issue I was bugging you about before.
~def

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Quote:
Original post by gorogoro
So I changed the Update code to something like this:

*** Source Snippet Removed ***
But that if is really really ugly. And things are kept hard coded. :s


I didn't mean to clamp it in here, but immediately when you're geting the value from the timer (possibly in the main loop). This kind of hardcoding is well known - it enforces slowdown of the gameplay when desired frame rate cannot be achieved.

Quote:
Original post by gorogoro
By the way with this if statment the thing works just fine.


Good for you!
Now go fix that mass/force issue I was bugging you about before.
~def



ARGH! I'm freaking out and running out of time! I don't now how to fix this stuff :p. Because the value 0.0065 (if(elapsedTime > 0.0099)elapsedTime = 0.0065) is working on my computer. But who garanties that it is still going to work on other computer or even at XBox360?? :S DAmned.

I'm looking to the files, with lot of values, and I don't now what to do. This elapsedTime is messing me a lot.

Here is the code I'm using to calculate the elapsedTime:


static double lastTime = Core::GetTimer().GetTimeSec();
double curDeltaTime = Core::GetTimer().GetTimeSec() - lastTime;

// update last time
lastTime += curDeltaTime;





Wich is done at every rendering step!

The elapsedTime is the lastTime variable.

Share this post


Link to post
Share on other sites
Quote:
Original post by gorogoro
Quote:
Original post by deffer
Quote:
Original post by gorogoro
So I changed the Update code to something like this:

*** Source Snippet Removed ***
But that if is really really ugly. And things are kept hard coded. :s


I didn't mean to clamp it in here, but immediately when you're geting the value from the timer (possibly in the main loop). This kind of hardcoding is well known - it enforces slowdown of the gameplay when desired frame rate cannot be achieved.

Quote:
Original post by gorogoro
By the way with this if statment the thing works just fine.


Good for you!
Now go fix that mass/force issue I was bugging you about before.
~def



ARGH! I'm freaking out and running out of time! I don't now how to fix this stuff :p. Because the value 0.0065 (if(elapsedTime > 0.0099)elapsedTime = 0.0065) is working on my computer. But who garanties that it is still going to work on other computer or even at XBox360?? :S DAmned.

I'm looking to the files, with lot of values, and I don't now what to do. This elapsedTime is messing me a lot.

Here is the code I'm using to calculate the elapsedTime:

*** Source Snippet Removed ***

Wich is done at every rendering step!

The elapsedTime is the lastTime variable.


One thing I just remembered now. I'm always using the World cordinate system. Could it be wrong? Should I use the local coordinate systems?

Share this post


Link to post
Share on other sites
Quote:
Original post by gorogoro
Here is the code I'm using to calculate the elapsedTime:

*** Source Snippet Removed ***

Wich is done at every rendering step!

The elapsedTime is the lastTime variable.


You should definitely use "curDeltaTime" variable.


static double lastTime = Core::GetTimer().GetTimeSec();
double curDeltaTime = Core::GetTimer().GetTimeSec() - lastTime;

// update last time
lastTime += curDeltaTime;

const double timeDiffToUpdate = clampMinMax(curDeltaTime, 0, 1.0/g_MinFrameRate);

// do various updates using only "timeDiffToUpdate" variable
myAgent.Update(timeDiffToUpdate);
myCamera.Update(timeDiffToUpdate);
// ...



Actually, you should check if this actually is the problem you were facing and "you think" you've resolved. Is "curDeltaTime" happen to be negative sometimes? Is it exceeding some high treshold value? If both answers are: no - the problem lies totally elsewhere.

Quote:
Original post by gorogoro
One thing I just remembered now. I'm always using the World cordinate system. Could it be wrong? Should I use the local coordinate systems?


It hardly matters, so you ought to use the one that more intuitively fits the concept. In other words, nope, you should stick to World Coordinates.

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Quote:
Original post by gorogoro
Here is the code I'm using to calculate the elapsedTime:

*** Source Snippet Removed ***

Wich is done at every rendering step!

The elapsedTime is the lastTime variable.


You should definitely use "curDeltaTime" variable.

*** Source Snippet Removed ***

Actually, you should check if this actually is the problem you were facing and "you think" you've resolved. Is "curDeltaTime" happen to be negative sometimes? Is it exceeding some high treshold value? If both answers are: no - the problem lies totally elsewhere.

Quote:
Original post by gorogoro
One thing I just remembered now. I'm always using the World cordinate system. Could it be wrong? Should I use the local coordinate systems?


It hardly matters, so you ought to use the one that more intuitively fits the concept. In other words, nope, you should stick to World Coordinates.



Thanks a Lot for all your support!
It was my mistake, I'm using the curDeltaTime off course.
It never have negative values. But sometimes I guess it gets values to big (thats's when it gets bad values).
Your saying that I should clmap the value to be in a certain range. But What range? How could I know what is the acceptable range??

Share this post


Link to post
Share on other sites
And is that procedure OK? Is it usual to do in games?
I should say that this game is going to be plattform independent (should work on PC and Xbox for now, but later it is going to work on ps3 and other consoles).

Share this post


Link to post
Share on other sites
Quote:
Original post by gorogoro
And is that procedure OK? Is it usual to do in games?
I should say that this game is going to be plattform independent (should work on PC and Xbox for now, but later it is going to work on ps3 and other consoles).


If that's the case, then it is not OK.

Bottom line is: this should work without any clamping whatsoever. If you are sure that timer is giving you values that are causing glithes, then you should definitely talk to the guys responsible for that module. On the other hand: I personally doubt that it is timer's fault, even thought you said that after clamping things run smoothly.

Again, I advice you to debug your code step-by-step in your debugger to see with your very eyes how the glithes are born. Without this you're dancing in the dark, and even won't be able to convince anyone in your team that they should help you about it. Try using some fake-timer values, so you could be reproducing the situation in different scenarios, causing the glithes or not - thus giving you some general direction - and then, using values that you're sure are causing glitches, examine the code flow thoroughly in your debugger.

Share this post


Link to post
Share on other sites
OK! Once more thank you a lot for the suport!

Now you can call me stupid!
Bug fixed and as all bug this was a really really stupid thing!
In the beggining of the project I make this:

[source snap="cpp"]
//TODO: talk to the guy of fisycs to set this properly using phisics engine
Vector3f GetVelocity()
{
return Vector3f(0,1,0);
}



And I forget it completly even when I was updating the m_velocity value.
ARGH!!!!!! Now I'm going to jump of a bridge. :p

Share this post


Link to post
Share on other sites
OK! Once more thank you a lot for the suport!

Now you can call me stupid!
Bug fixed and as all bug this was a really really stupid thing!
In the beggining of the project I make this:


//TODO: talk to the guy of fisycs to set this properly using phisics engine
Vector3f GetVelocity()
{
return Vector3f(0,1,0);
}



And I forget it completly even when I was updating the m_velocity value.
ARGH!!!!!! Now I'm going to jump of a bridge. :p

Share this post


Link to post
Share on other sites

This topic is 4198 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this