[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?


* 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
    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