Steeering behaviours
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???
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]
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]
June 17, 2006 06:34 AM
Hi!
try not multiplying your accelaration by elapsedTime (only multiply in the position update).
Greetings!
Vicente
try not multiplying your accelaration by elapsedTime (only multiply in the position update).
Greetings!
Vicente
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
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
You're mixing mass/accel/force too much. I fixed some things in your code:
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).
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).
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
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.
Quote: Original post by defferQuote: 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]
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]
Quote: Original post by defferQuote: 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]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement