Difference between revisions of "Mirror Movement"

From Robowiki
Jump to navigation Jump to search
(Major edit.)
(Rewrite page)
 
Line 1: Line 1:
'''Mirror Movement''' is a form of [[One on One|1v1]] movement that tries to copy the movement of the enemy. Though it can be effective against opponents with strong movement, it is utterly useless against opponents with weak movement or [[oldwiki:AntiMirrorGun|antimirror targeting]].
+
'''Mirror Movement''' is a form of [[1v1]] movement that tries to imitate the movement of the enemy. Though it can be effective against opponents with strong movement, it is utterly useless against opponents with weak movement or [[oldwiki:AntiMirrorSystem|anti-mirror targeting]].
  
There are several styles of mirror movement, ranging from very simple perpendicular mirror movement to the more complex coordinate mirror movement.
+
Implementing mirror movement requires [[One on One Radar|a decent radar lock]].
  
== Implementations ==
+
The current state-of-art mirror is '''[[PolishedRuby]]'''.
Here are some code examples of mirror movement.  For them to work properly, a decent [[One on One Radar|radar lock]] is required.
 
  
=== Perpendicular Mirror Movement ===
+
== Coordinate Mirror Movement ==
This is among the simplest and smallest of all movements, though it isn't very effective.
+
This style of mirror movement tries to move to a point "opposite" the opponent. It requires a [[GoTo]] method, such as this one:
This will turn perpendicular to the enemy and move at roughly the same velocity.
+
 
<syntaxhighlight>
+
<syntaxhighlight lang="java">
//Put this code in the onScannedRobot area of your robot.
+
private void goTo(double x, double y) {
setTurnRightRadians(Math.cos(e.getBearingRadians()));
+
    /* Transform our coordinates into a vector */
setAhead(4 * e.getVelocity());
+
    x -= getX();
 +
    y -= getY();
 +
 +
    /* Calculate the angle to the target position */
 +
    double angleToTarget = Math.atan2(x, y);
 +
 +
    /* Calculate the turn required get there */
 +
    double targetAngle = Utils.normalRelativeAngle(angleToTarget - getHeadingRadians());
 +
 +
    /*
 +
    * The Java Hypot method is a quick way of getting the length
 +
    * of a vector. Which in this case is also the distance between
 +
    * our robot and the target location.
 +
    */
 +
    double distance = Math.hypot(x, y);
 +
 +
    /* This is a simple method of performing set front as back */
 +
    double turnAngle = Math.atan(Math.tan(targetAngle));
 +
    setTurnRightRadians(turnAngle);
 +
    if(targetAngle == turnAngle) {
 +
        setAhead(distance);
 +
    } else {
 +
        setBack(distance);
 +
    }
 +
}
 +
</syntaxhighlight>
 +
 
 +
It also requires calculating the coordinates of the enemy robot:
 +
 
 +
<syntaxhighlight lang="java">
 +
public void onScannedRobot(ScannedRobotEvent e) {
 +
    double enemyX = getX() + e.getDistance() * Math.sin(getHeadingRadians() + e.getBearingRadians());
 +
    double enemyY = getY() + e.getDistance() * Math.cos(getHeadingRadians() + e.getBearingRadians());
 +
 
 +
    // TODO
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Angular Mirror Movement ===
+
The enemy coordinates must then be transformed, before being passed to the <tt>goTo()</tt> function. The transformation depends on the type of mirroring:
This just tries to move in the same direction and at the same speed as the enemy.
+
 
<syntaxhighlight>
+
; Vertical line-reflection
//Put this code in the onScannedRobot area of your robot.
+
: <syntaxhighlight lang="java">goTo(getBattleFieldWidth() - enemyX, enemyY);</syntaxhighlight>
setTurnRightRadians(Utils.normalRelativeAngle(e.getHeadingRadians() - getHeadingRadians()));
+
 
setAhead(e.getVelocity() * 1000);
+
; Horizontal line-reflection
setMaxVelocity(Math.abs(e.getVelocity()));
+
: <syntaxhighlight lang="java">goTo(enemyX, getBattleFieldHeight() - enemyY);</syntaxhighlight>
 +
 
 +
; Point-reflection over the battlefield center
 +
: <syntaxhighlight lang="java">goTo(getBattleFieldWidth() - enemyX, getBattleFieldHeight() - enemyY);</syntaxhighlight>
 +
 
 +
== Relative Mirror Movement ==
 +
This type of movement attempts to imitate the opponent's movement (same direction and same velocity), starting at the bot's current location. For instance, if the enemy moves upward 100 units, your bot will also move upward 100 units. Not very effective against most guns, and '''must''' be combined with [[Wall Smoothing]] for any level of usefulness.
 +
 
 +
<syntaxhighlight lang="java">
 +
public void onScannedRobot(ScannedRobotEvent e) {
 +
    setTurnRight(Utils.normalRelativeAngleDegrees(e.getHeading() - getHeading()));
 +
    setMaxVelocity(Math.abs(e.getVelocity()));
 +
    setAhead(Double.POSITIVE_INFINITY * e.getVelocity());
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Coordinate Mirror Movement ===
+
== Perpendicular Mirror Movement ==
This style tries to move symmetrically to a point on the battlefield, usually the center. For example, if the enemy were retreating from the center, then so would the mirror bot(as opposed to angular mirror movement, which would advance toward the enemy).
+
This type of movement will circle the enemy, by turning perpendicular to it and moving at roughly the same velocity.
  
The following code is from mn.micro.perceptual.Mimic 1.0.0.
+
<syntaxhighlight lang="java">
<syntaxhighlight>
+
public void onScannedRobot(ScannedRobotEvent e) {
//Put this code in the onScannedRobot area of your robot.
+
    setTurnRightRadians(Math.cos(e.getBearingRadians()));
final double headOnBearing = event.getBearingRadians() + getHeadingRadians();
+
    setAhead(4 * e.getVelocity());
final double destinationDistanceX = getBattleFieldWidth() - sin(headOnBearing) * event.getDistance() - getX() * 2;
 
final double destinationDistanceY = getBattleFieldHeight() - cos(headOnBearing) * event.getDistance() - getY() * 2;
 
double destinationDistance = sqrt(destinationDistanceX * destinationDistanceX + destinationDistanceY * destinationDistanceY);
 
destinationDistance = destinationDistance > 0.001 ? destinationDistance : 0;
 
double turn = (destinationDistance > 0 ? atan2(destinationDistanceX, destinationDistanceY) : event.getHeadingRadians()) - getHeadingRadians();
 
double ahead = POSITIVE_INFINITY;
 
if (cos(turn) < 0) {
 
    turn -= PI;
 
    ahead = NEGATIVE_INFINITY;
 
 
}
 
}
setTurnRightRadians(normalRelativeAngle(turn));
 
setAhead(ahead);
 
setMaxVelocity(destinationDistance);
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
== See Also ==
 
== See Also ==
* [[oldwiki:MirrorMovement]]
+
* [[oldwiki:MirrorMovement|Mirror Movement on the old RoboWiki]]
 +
 
 
[[Category:Terminology]]
 
[[Category:Terminology]]
 
[[Category:Movement]]
 
[[Category:Movement]]

Latest revision as of 22:11, 28 August 2017

Mirror Movement is a form of 1v1 movement that tries to imitate the movement of the enemy. Though it can be effective against opponents with strong movement, it is utterly useless against opponents with weak movement or anti-mirror targeting.

Implementing mirror movement requires a decent radar lock.

The current state-of-art mirror is PolishedRuby.

Coordinate Mirror Movement

This style of mirror movement tries to move to a point "opposite" the opponent. It requires a GoTo method, such as this one:

private void goTo(double x, double y) {
    /* Transform our coordinates into a vector */
    x -= getX();
    y -= getY();
 
    /* Calculate the angle to the target position */
    double angleToTarget = Math.atan2(x, y);
 
    /* Calculate the turn required get there */
    double targetAngle = Utils.normalRelativeAngle(angleToTarget - getHeadingRadians());
 
    /* 
     * The Java Hypot method is a quick way of getting the length
     * of a vector. Which in this case is also the distance between
     * our robot and the target location.
     */
    double distance = Math.hypot(x, y);
 
    /* This is a simple method of performing set front as back */
    double turnAngle = Math.atan(Math.tan(targetAngle));
    setTurnRightRadians(turnAngle);
    if(targetAngle == turnAngle) {
        setAhead(distance);
    } else {
        setBack(distance);
    }
}

It also requires calculating the coordinates of the enemy robot:

public void onScannedRobot(ScannedRobotEvent e) {
    double enemyX = getX() + e.getDistance() * Math.sin(getHeadingRadians() + e.getBearingRadians());
    double enemyY = getY() + e.getDistance() * Math.cos(getHeadingRadians() + e.getBearingRadians());

    // TODO
}

The enemy coordinates must then be transformed, before being passed to the goTo() function. The transformation depends on the type of mirroring:

Vertical line-reflection
goTo(getBattleFieldWidth() - enemyX, enemyY);
Horizontal line-reflection
goTo(enemyX, getBattleFieldHeight() - enemyY);
Point-reflection over the battlefield center
goTo(getBattleFieldWidth() - enemyX, getBattleFieldHeight() - enemyY);

Relative Mirror Movement

This type of movement attempts to imitate the opponent's movement (same direction and same velocity), starting at the bot's current location. For instance, if the enemy moves upward 100 units, your bot will also move upward 100 units. Not very effective against most guns, and must be combined with Wall Smoothing for any level of usefulness.

public void onScannedRobot(ScannedRobotEvent e) {
    setTurnRight(Utils.normalRelativeAngleDegrees(e.getHeading() - getHeading()));
    setMaxVelocity(Math.abs(e.getVelocity()));
    setAhead(Double.POSITIVE_INFINITY * e.getVelocity());
}

Perpendicular Mirror Movement

This type of movement will circle the enemy, by turning perpendicular to it and moving at roughly the same velocity.

public void onScannedRobot(ScannedRobotEvent e) {
    setTurnRightRadians(Math.cos(e.getBearingRadians()));
    setAhead(4 * e.getVelocity());
}

See Also