Beispiel #1
0
        // XXX 4-23-03: Temporary work around (see comment above)
        //
        // Checks for intersection of the given spherical obstacle with a
        // volume of "likely future vehicle positions": a cylinder along the
        // current path, extending minTimeToCollision seconds along the
        // forward axis from current position.
        //
        // If they intersect, a collision is imminent and this function returns
        // a steering force pointing laterally away from the obstacle's center.
        //
        // Returns a zero vector if the obstacle is outside the cylinder
        //
        // xxx couldn't this be made more compact using localizePosition?

        Vector3 steerToAvoid(AbstractVehicle v, float minTimeToCollision)
        {
            // minimum distance to obstacle before avoidance is required
            float minDistanceToCollision = minTimeToCollision * v.Speed();
            float minDistanceToCenter    = minDistanceToCollision + radius;

            // contact distance: sum of radii of obstacle and vehicle
            float totalRadius = radius + v.Radius();

            // obstacle center relative to vehicle position
            Vector3 localOffset = center - v.Position;

            // distance along vehicle's forward axis to obstacle's center
            float   forwardComponent = Vector3.Dot(localOffset, v.Forward());
            Vector3 forwardOffset    = forwardComponent * v.Forward();

            // offset from forward axis to obstacle's center
            Vector3 offForwardOffset = localOffset - forwardOffset;

            // test to see if sphere overlaps with obstacle-free corridor
            bool inCylinder = offForwardOffset.magnitude < totalRadius;
            bool nearby     = forwardComponent < minDistanceToCenter;
            bool inFront    = forwardComponent > 0;

            // if all three conditions are met, steer away from sphere center
            if (inCylinder && nearby && inFront)
            {
                return(offForwardOffset * -1);
            }
            else
            {
                return(Vector3.zero);
            }
        }
Beispiel #2
0
        // Given the time until nearest approach (predictNearestApproachTime)
        // determine position of each vehicle at that time, and the distance
        // between them
        float computeNearestApproachPositions(AbstractVehicle other, float time)
        {
            Vector3 myTravel    = Forward() * Speed() * time;
            Vector3 otherTravel = other.Forward() * other.Speed() * time;

            Vector3 myFinal    = Position + myTravel;
            Vector3 otherFinal = other.Position + otherTravel;

            // xxx for annotation
            ourPositionAtNearestApproach = myFinal;
            hisPositionAtNearestApproach = otherFinal;

            return((myFinal - otherFinal).magnitude);
        }
Beispiel #3
0
        // ----------------------------------------------------------------------------
        // evasion of another vehicle
        public Vector3 steerForEvasion(AbstractVehicle menace, float maxPredictionTime)
        {
            // offset from this to menace, that distance, unit vector toward menace
            Vector3 offset   = menace.Position - Position;
            float   distance = offset.magnitude;

            float roughTime      = distance / menace.Speed();
            float predictionTime = ((roughTime > maxPredictionTime) ?
                                    maxPredictionTime :
                                    roughTime);

            Vector3 target = menace.PredictFuturePosition(predictionTime);

            return(steerForFlee(target));
        }
Beispiel #4
0
        // ----------------------------------------------------------------------------
        // Unaligned collision avoidance behavior: avoid colliding with other nearby
        // vehicles moving in unconstrained directions.  Determine which (if any)
        // other other vehicle we would collide with first, then steers to avoid the
        // site of that potential collision.  Returns a steering force vector, which
        // is zero length if there is no impending collision.
        public Vector3 steerToAvoidNeighbors(float minTimeToCollision, ArrayList others)
        {
            // first priority is to prevent immediate interpenetration
            Vector3 separation = steerToAvoidCloseNeighbors(0, others);

            if (separation != Vector3.zero)
            {
                return(separation);
            }

            // otherwise, go on to consider potential future collisions
            float           steer  = 0;
            AbstractVehicle threat = null;

            // Time (in seconds) until the most immediate collision threat found
            // so far.  Initial value is a threshold: don't look more than this
            // many frames into the future.
            float minTime = minTimeToCollision;

            // xxx solely for annotation
            Vector3 xxxThreatPositionAtNearestApproach = new Vector3();
            Vector3 xxxOurPositionAtNearestApproach    = new Vector3();

            // for each of the other vehicles, determine which (if any)
            // pose the most immediate threat of collision.
            //for (AVIterator i = others.begin(); i != others.end(); i++)
            for (int i = 0; i < others.Count; i++)
            {
                AbstractVehicle other = (AbstractVehicle)others[i];
                if (other != this)
                {
                    // avoid when future positions are this close (or less)
                    float collisionDangerThreshold = Radius() * 2;

                    // predicted time until nearest approach of "this" and "other"
                    float time = predictNearestApproachTime(other);

                    // If the time is in the future, sooner than any other
                    // threatened collision...
                    if ((time >= 0) && (time < minTime))
                    {
                        // if the two will be close enough to collide,
                        // make a note of it
                        if (computeNearestApproachPositions(other, time)
                            < collisionDangerThreshold)
                        {
                            minTime = time;
                            threat  = other;
                            xxxThreatPositionAtNearestApproach
                                = hisPositionAtNearestApproach;
                            xxxOurPositionAtNearestApproach
                                = ourPositionAtNearestApproach;
                        }
                    }
                }
            }

            // if a potential collision was found, compute steering to avoid
            if (threat != null)
            {
                // parallel: +1, perpendicular: 0, anti-parallel: -1
                float parallelness = Vector3.Dot(Forward(), threat.Forward());
                float angle        = 0.707f;

                if (parallelness < -angle)
                {
                    // anti-parallel "head on" paths:
                    // steer away from future threat position
                    Vector3 offset  = xxxThreatPositionAtNearestApproach - Position;
                    float   sideDot = Vector3.Dot(offset, Side());
                    steer = (sideDot > 0) ? -1.0f : 1.0f;
                }
                else
                {
                    if (parallelness > angle)
                    {
                        // parallel paths: steer away from threat
                        Vector3 offset  = threat.Position - Position;
                        float   sideDot = Vector3.Dot(offset, Side());
                        steer = (sideDot > 0) ? -1.0f : 1.0f;
                    }
                    else
                    {
                        // perpendicular paths: steer behind threat
                        // (only the slower of the two does this)
                        if (threat.Speed() <= Speed())
                        {
                            float sideDot = Vector3.Dot(Side(), threat.Velocity());
                            steer = (sideDot > 0) ? -1.0f : 1.0f;
                        }
                    }
                }

                annotateAvoidNeighbor(threat,
                                      steer,
                                      xxxOurPositionAtNearestApproach,
                                      xxxThreatPositionAtNearestApproach);
            }

            return(Side() * steer);
        }