Difference between revisions of "Getting started with angles"

From Robowiki
Jump to navigation Jump to search
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
Angles are important for [[Radar]], [[Movement]], and [[Targeting]].
+
Angles are important for [[Radar]], [[Movement]], and [[Targeting]]. Some trigonometric methods measure angles in radians, but Robocode has different methods for both radians and degrees.
  
 
== Absolute Bearing ==
 
== Absolute Bearing ==
  
 
Absolute Bearing is the absolute angle from one robot to another robot. You can calculate the Absolute Bearing from your robot in onScannedRobot as  
 
Absolute Bearing is the absolute angle from one robot to another robot. You can calculate the Absolute Bearing from your robot in onScannedRobot as  
  e.getBearingRadians() + getHeadingRadians()
+
  absoluteBearing = e.getBearingRadians() + getHeadingRadians();
  
The robot's heading is an absolute angle, and the bearing to the scanned robot is a relative angle.
+
The robot's heading is an absolute angle (0 to 360 degrees), and the bearing to the scanned robot is a relative angle (-180 to 180 degrees).
  
 
To get the other robot's Absolute Bearing to you, add Math.PI (180 degrees). To get the perpendicular angle so you can orbit them, add Math.PI/2 (90 degrees). [[NanoBots]] typically orbit with Math.cos(e.getBearingRadians()) instead.
 
To get the other robot's Absolute Bearing to you, add Math.PI (180 degrees). To get the perpendicular angle so you can orbit them, add Math.PI/2 (90 degrees). [[NanoBots]] typically orbit with Math.cos(e.getBearingRadians()) instead.
  
To calculate the Absolute Bearing from one location1 to location2, you can use:
+
To calculate the Absolute Bearing from a source location to another location, you can use a method like the following from [[GFTargetingBot]]:
  absoluteBearing = Math.atan2(x1 - x2, y1 - y2);
+
  static double absoluteBearing(Point2D source, Point2D target) {
 +
return Math.atan2(target.getX() - source.getX(), target.getY() - source.getY());
 +
}
  
 
== Moving to an angle ==
 
== Moving to an angle ==
Line 22: Line 24:
  
 
== Utils.normalRelativeAngle ==
 
== Utils.normalRelativeAngle ==
Angles are only meaningful in a certain range, so simple arithmetic can cause problems. Luckily, Robocode provides a method to normalize relative angles. This is used very often in targeting to get the gun turn amount:
+
Large turns in one direction take a lot more time than small turns in the opposite direction, so doing simple arithmetic with angles can cause problems. Luckily, Robocode provides a method to normalize relative angles. This is used very often in targeting to get the gun turn amount:
 
  setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing + targetingOffset - getGunHeadingRadians()));
 
  setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing + targetingOffset - getGunHeadingRadians()));
  
 
== Utils.normalAbsoluteAngle ==
 
== Utils.normalAbsoluteAngle ==
This method normalizes absolute angles (0 to 360 degrees). It is useful when counting data about all angles around the robot. [[Cotillion]] uses it for [[Multiple Choice]] [[Pattern Matching]].
+
This method normalizes absolute angles. It is useful when counting data about all angles around the robot. [[Cotillion]] uses it for [[Multiple Choice]] [[Pattern Matching]].
  
 
== Comparing angles ==
 
== Comparing angles ==
To calculate how far one angle is from another, you can use Math.abs(Utils.normalRelativeAngle(angleA - angleB)).
+
To calculate how far one angle is from another, you can use Math.abs(Utils.normalRelativeAngle(absoluteAngleA - absoluteAngleB)).
  
 
== Relative bins ==
 
== Relative bins ==
Line 42: Line 44:
 
  statistics[index = ((int)Math.round((angle / Math.PI*2) * BINS))]++;
 
  statistics[index = ((int)Math.round((angle / Math.PI*2) * BINS))]++;
 
  angle = index * Math.PI*2 / BINS;
 
  angle = index * Math.PI*2 / BINS;
 +
 +
== Projecting a location ==
 +
To obtain a new location at a certain distance and angle from a source location, you can use a method like the following from [[GFTargetingBot]]:
 +
static Point2D project(Point2D sourceLocation, double angle, double length) {
 +
return new Point2D.Double(sourceLocation.getX() + Math.sin(angle) * length, sourceLocation.getY() + Math.cos(angle) * length);
 +
}

Latest revision as of 21:57, 16 January 2026

Angles are important for Radar, Movement, and Targeting. Some trigonometric methods measure angles in radians, but Robocode has different methods for both radians and degrees.

Absolute Bearing

Absolute Bearing is the absolute angle from one robot to another robot. You can calculate the Absolute Bearing from your robot in onScannedRobot as

absoluteBearing = e.getBearingRadians() + getHeadingRadians();

The robot's heading is an absolute angle (0 to 360 degrees), and the bearing to the scanned robot is a relative angle (-180 to 180 degrees).

To get the other robot's Absolute Bearing to you, add Math.PI (180 degrees). To get the perpendicular angle so you can orbit them, add Math.PI/2 (90 degrees). NanoBots typically orbit with Math.cos(e.getBearingRadians()) instead.

To calculate the Absolute Bearing from a source location to another location, you can use a method like the following from GFTargetingBot:

static double absoluteBearing(Point2D source, Point2D target) {
return Math.atan2(target.getX() - source.getX(), target.getY() - source.getY());
}

Moving to an angle

The easiest way to move your robot at a certain angle is the following:

angle = targetAngle - getHeadingRadians();
setAhead(Math.cos(angle) * bigNumber);
setTurnRightRadians(Math.tan(angle));

An alternative to slowly turning your robot with Utils.normalRelativeAngle, this technique reverses movement direction when the robot needs to make a very large turn.

Utils.normalRelativeAngle

Large turns in one direction take a lot more time than small turns in the opposite direction, so doing simple arithmetic with angles can cause problems. Luckily, Robocode provides a method to normalize relative angles. This is used very often in targeting to get the gun turn amount:

setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing + targetingOffset - getGunHeadingRadians()));

Utils.normalAbsoluteAngle

This method normalizes absolute angles. It is useful when counting data about all angles around the robot. Cotillion uses it for Multiple Choice Pattern Matching.

Comparing angles

To calculate how far one angle is from another, you can use Math.abs(Utils.normalRelativeAngle(absoluteAngleA - absoluteAngleB)).

Relative bins

For Visit Count Stats with relative angles, you need to have a total number of bins and a middle factor index (for the Absolute Bearing). To convert a relative angle to a bin index, you can normalize the angle to 0-1, multiply by the number of bins and round, then add the middle factor. In Guess Factor Targeting, the maximum angle is the Maximum Escape Angle.

statistics[index = ((int)Math.round((angle / maxAngle) * BINS) + MIDDLE)]++;

To convert an index into an angle, simply invert:

angle = (index - MIDDLE) * maxAngle / BINS;

Absolute bins

Absolute bins don't need a middle factor index, and the maximum angle is a full circle (Math.PI*2 or 360 degrees).

statistics[index = ((int)Math.round((angle / Math.PI*2) * BINS))]++;
angle = index * Math.PI*2 / BINS;

Projecting a location

To obtain a new location at a certain distance and angle from a source location, you can use a method like the following from GFTargetingBot:

static Point2D project(Point2D sourceLocation, double angle, double length) {
return new Point2D.Double(sourceLocation.getX() + Math.sin(angle) * length, sourceLocation.getY() + Math.cos(angle) * length);
}