Enemy Dodging Movement

From Robowiki
Revision as of 19:12, 24 October 2009 by Jdev (talk | contribs) (Movement method description)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

A method for avoiding collisions with enemies.

How it works

General idea is: in Enemy Dodging Movement (EDM) you're generate set of points around yours robot, calculate avarenge distance to enemies for each one and go to point with minamal value.

Graphical demonstration

Edm demo.GIF

This image is my demo robot for this method. There're:

  • red squares - enemies positions
  • blue circle - danger area (enemies outside this area is ignored)
  • points around EDMRobot - destination point set. White points is good, red is bad
  • bold white point - destination point

Implementation

/**
 * This class is implement Enemy dodging movement method
 * 
 * @author jdev
 */
public class EnemyDodgingMovement {

    private static final int ACTIVITY_AREA_MARGIN = 20;
    private static final int FIELD_OF_VISION = 50;
    private static final int DANGER_DISTANCE = FIELD_OF_VISION * 3;

    private final Robot robot;
    private final Rectangle activityArea;

    public EnemyDodgingMovement(Robot robot) {
        this.robot = robot;

        activityArea = new Rectangle(ACTIVITY_AREA_MARGIN, ACTIVITY_AREA_MARGIN,
                (int)robot.getBattleFieldWidth() - ACTIVITY_AREA_MARGIN * 2,
                (int)robot.getBattleFieldHeight() - ACTIVITY_AREA_MARGIN * 2);
    }

    /**
     * Method to calculate farest point from enemies
     * @param enemies position of enemies
     * @return farest point from enemies
     */
    public Point2D.Double getDestination(Collection<Point2D.Double> enemies) {
        final Collection<EDMPoint> points = getPoints(FIELD_OF_VISION, enemies);
        
        double maxAvgDist = 0;
        EDMPoint destination = null;
        
        for (EDMPoint p : points) {
            double avgDist = calculateAvgDistance(p, enemies);
            if (avgDist > maxAvgDist) {
                maxAvgDist = avgDist;
                destination = p;
            }
        }

        return destination;
    }

    /**
     * Returns the collection of points, which are located on circle with radius = <code>dist</code> and with center
     * in [<code>robot.getX()</code>, <code>robot.getY()</code>]
     * @param dist distance to probably destination points from robot
     * @param enemies enemies positions
     * @return Returns the collection of points 
     */
    private Collection<EDMPoint> getPoints(double dist, Collection<Point2D.Double> enemies) {
        final Collection<EDMPoint> points = new LinkedList<EDMPoint>();
        final Point2D.Double myPos = new Point2D.Double(robot.getX(), robot.getY());
        for (double angle = 0; angle < PI * 2; angle += PI / 9) {
            final EDMPoint p = new EDMPoint(myPos.x + sin(angle) * dist,
                    myPos.y + cos(angle) * dist);

            if (!activityArea.contains(p)) {
                continue;
            }
            p.avgDistance = calculateAvgDistance(p, enemies);
            points.add(p);
        }

        return points;
    }

    /**
     * Calculates avarenge distance from point <code>point</code> to enemies in <code>enemies</code>
     * @param point point to calculate averenge distance
     * @param enemies enemies positions
     * @return averenge distance
     */
    private double calculateAvgDistance(Point2D.Double point, Collection<Point2D.Double> enemies) {
        double distanceSum = 0;
        int closeEnemyCount = 0;
        for (Point2D.Double p : enemies) {
            final double distance = p.distance(point);
            if (p.distance(robot.getX(), robot.getY()) > DANGER_DISTANCE) {
                continue;
            }
            
            distanceSum += distance;
            closeEnemyCount++;
        }

        return distanceSum / (double)(closeEnemyCount > 0 ? closeEnemyCount : 1);
    }

    /**
     * Paints a EDM's model
     * @param g graphics to paint
     * @param enemies enemies positions
     */
    public void paint(Graphics2D g, Collection<Point2D.Double> enemies) {
        g.setColor(Color.WHITE);
        final Collection<EDMPoint> points = getPoints(FIELD_OF_VISION, enemies);
        double maxAvgDist = 0;
        double minAvgDist = Double.MAX_VALUE;
        for (EDMPoint p : points) {
            if (p.avgDistance < minAvgDist) {
                minAvgDist = p.avgDistance;
            }
            if (p.avgDistance > maxAvgDist) {
                maxAvgDist = p.avgDistance;
            }
        }

        for (EDMPoint rp : points) {

            int radius = 4;
            int gb = (int) (255 * (rp.avgDistance - minAvgDist) / (maxAvgDist - minAvgDist));
            if (gb < 0) {
                gb = 0;
            } else if (gb > 255) {
                gb = 255;
            }
            g.setColor(new Color(255, gb, gb));
            g.fillOval((int) Math.round(rp.x - radius / 2), (int) Math.round(rp.y - radius / 2), radius, radius);
            if (rp.avgDistance == maxAvgDist) {
                radius = 6;
                g.drawOval((int) Math.round(rp.x - radius / 2), (int) Math.round(rp.y - radius / 2), radius, radius);
            }
        }

        g.setColor(Color.BLUE);
        final int fieldOfVisionRadius = DANGER_DISTANCE * 2;
        g.drawOval((int)robot.getX() - fieldOfVisionRadius / 2, (int)robot.getY() - fieldOfVisionRadius / 2,
                fieldOfVisionRadius, fieldOfVisionRadius);
    }

}
/**
 * Class to represent Point in EDM method. Externds Point2D.Double and adds field <code>avgDistance</code>,
 * which means averegene distance to enemies in EDM 
 *
 * @author jdev
 */
public class EDMPoint extends Point2D.Double {

    public double avgDistance;

    public EDMPoint(double x, double y) {
        super(x, y);
    }
}

Advantages

  • Easy to implement
  • IF it's possible, this method will gice you point where you will not hit an enemy

Disadvantages

  • It's clear tactical "method", so it must be combined with any "strategical" method, for example Minimum_Risk_Movement

--Jdev 18:12, 24 October 2009 (UTC)