[Sidefx-houdini-list] Natural Behaviour in Crowd Obstacle avoidance
Sean Lewkiw
slewkiw at cinesite.com
Tue Jan 30 16:57:05 EST 2018
I have a question about crowd avoidance. I have a sim in which my crowd
has to avoid a simple obstacle. The POP steer obstacle DOP works, but
results in very zombie-like behaviour.
What happens is when an agent suddenly becomes aware of an obstacle, it
just swivels on its heel and turns 90 degrees in a step or two. Obviously,
you or I will slowly drift away from obstacles that are obvious and just
sitting there instead of walking right up to something at full speed and
turning at the very last possible second.
I can adjust the front search distance, but the only thing this does is
offset this same behaviour. Turning "sample weight bias" down to zero
actually makes for much more natural behaviour, but then they don't avoid
each other.
I looked at the snippet and it calls this function below. (Rookie
mistake! Look they are using Cramer's law! Who uses that any more?! * )
Has anyone had any experience getting more natural obstacle avoidance?
Thanks,
Sean
* NOTE: This is a joke. I have no idea what Cramer's law is.
vector AGENTobstacleForce(const vector p1; const vector p2; const vector
pos; const vector vel; const float rad; const float k; const float tau0;
export float tau)
{
// Vector from p1 of line segment to p2
vector relp = p2 - p1;
// Ensure that the agent is not penetrating the obstacle (perturb
endpoints along normal by radius of agent)
// Pertubation in both directions must be checked for min collision
time.
vector norm = norm2d(relp);
vector o1 = p1 + rad * norm;
vector o2 = p1 - rad * norm;
// Vector from first point on the line segment to the agent
vector po1 = pos - o1;
vector po2 = pos - o2;
// Solving po = t(vx + rx) + s(vy + ry) using Cramer's rule
float detv = det2d(vel, relp);
tau = -1;
if(detv > 0.00001f || detv < -0.00001f)
{
// Find the minimum time to collision to the line segment (same model as
agentInteractionForce), directed
// on normal to the line segment
float invdet = 1.0f/detv;
tau = AGENTsegCollisionTime(relp, vel, po1, invdet, tau);
tau = AGENTsegCollisionTime(relp, vel, po2, invdet, tau);
if(tau > 0)
{
vector dir = 0;
dir.x = -relp.z;
dir.z = relp.x;
float en = k * exp(-tau / tau0) / (tau * tau);
float cof = (en / detv) * (2 / tau + 1 / tau0);
return cof * dir;
}
}
return 0;
}
--
Sean Lewkiw
Cinesite MTL
More information about the Sidefx-houdini-list
mailing list