package neh; /** * This class contains a set of useful methods for programming * robocode robots, mainly dealing with distances and angles. * Most of these would actually work for any 2d application. All * functions use radians, not degrees. **/ public class RobocodeUtils { private RobocodeUtils() {} public static final double TWO_PI = Math.PI*2; public static final double HALF_PI = Math.PI/2; /**return the distance between (x1,y1) and (x2,y2)*/ public static double dist(double x1, double y1, double x2, double y2) { return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } /** * Normalizes an angle (reduces it to the coterminal angle theta * such that 0 < theta < 2*pi) **/ public static double normalizeHeading(double ang) { while (ang < 0) ang += TWO_PI; while (ang > TWO_PI) ang -= TWO_PI; return ang; } /** * Normalizes a bearing (reduces it to the coterminal angle theta * such that -pi < theta < pi) **/ public static double normalizeBearing(double ang) { while (ang < -Math.PI) ang += TWO_PI; while (ang > Math.PI) ang -= TWO_PI; return ang; } /**returns the bearing from (x1,y1) to (x2,y2) in the range -pi to pi*/ public static double getBearing( double x1,double y1, double x2,double y2 ) { double xo = x2-x1; double yo = y2-y1; return Math.atan2(xo,yo); } }
Here's a shorter, more efficient version of normalizeHeading:
public static final double normalizeHeading(double angle) { return Math.abs(angle % TWO_PI); }
And there are a couple versions of normalizeBearing floating around out there, but I think this is the smallest (accurate) version:
public static final double normalizeBearing(double angle) { return Math.atan2(Math.sin(angle), Math.cos(angle)); }
- nano
The Math.abs() version doesn't work correctly on negatives I don't think (not that simple). However, I figured out a way to make Robocode do it-
return robocode.util.Utils.normalAbsoluteAngle(angle);
In SillyBot, the way I do normalizeBearing is using the above:
return robocode.util.Utils.normalAbsoluteAngle(angle+Math.PI)-Math.PI;I hear that takes 1 byte more than the trig way nano showed, though, if you're worried about codesize.
Does anyone know if there are any other utils in the robocode class besides normalRelativeAngle and normalAbsoluteAngle?? - Tyrol
I don't know about the correctness of the normalizeHeading and normalizeBearing functions in this code, I think the following versions are functionally the same and are faster. --Quag?
public final static double normalizeBearing(final double ang) { return ang % Math.PI; }
public final static double normalizeHeading(final double ang) { final double result = ang % Math.PI; if (result < 0) return result + TWO_PI; return result; }
Quaq?, your code doesn't work right. I quickly wrote Normalizer (32 CodeSize) as an example:
public class Normalizer { public final static double PI2 = Math.PI*2; /** * Returns normalized heading (0 <= heading < 2*Pi). * @return 0 <= heading < 2*Pi */ public static double normalizeHeading(final double heading) { return (heading % PI2 + PI2) % PI2; } /** * Returns normalized bearing (-Pi <= bearing < Pi) * @return -Pi <= bearing < Pi */ public static double normalizeBearing(final double bearing) { return normalizeHeading(bearing + Math.PI) - Math.PI; } }Note that you can use normalizeAbsoluteAngle?() and normalizeRelativeAngle() of robocode.util.Utils (my IDE shows variables and methods if you open a .class, but doesn't try to get the inside of methods back - it shows nothing instead). Handy for NanoBots.
dist() is more efficient (less (code)size and faster) when written directly in Java ByteCode?, and getBearing() uses inefficient (more (code)size and slower) variables. -- Jonathan
Oooops... not quite enough test cases. :) Thanks for spotting my errors Jonathan. --Quag?
You can also use:
robocode.util.Utils.normalRelativeAngle(angle);Clemens(cr)