Difference between revisions of "Darkcanuck/VelocityTest"
Jump to navigation
Jump to search
Darkcanuck (talk | contribs) (testing getNewVelocity) |
Darkcanuck (talk | contribs) (uses right version now...) |
||
| Line 13: | Line 13: | ||
// init | // init | ||
| − | System.out.println(" | + | System.out.println("\nDarkcanuck's VelocityTest\n"); |
| − | testCase(Double.valueOf(args[0]), Double.valueOf(args[1])); | + | if (!args[0].equals("all")) { |
| + | testCase(Double.valueOf(args[0]), Double.valueOf(args[1])); | ||
| + | } else { | ||
| + | testCase(0, 6); | ||
| + | } | ||
} | } | ||
| Line 23: | Line 27: | ||
int tick = 0; | int tick = 0; | ||
| − | System.out.println("Starting velocity=" + velocity + " distance=" + distance | + | System.out.println("Starting velocity=" + velocity + " distance=" + distance); |
| − | while (newdist > 0. | + | while ((Math.abs(newvel)>0.00001) || (Math.abs(newdist)>0.00001)) { |
newvel = getNewVelocity(newvel, newdist); | newvel = getNewVelocity(newvel, newdist); | ||
newdist -= newvel; | newdist -= newvel; | ||
tick++; | tick++; | ||
| − | System.out.println(" " + tick + " velocity=" + newvel + " remain=" + newdist | + | System.out.println(" " + tick + " velocity=" + newvel + " remain=" + newdist); |
} | } | ||
System.out.println("\n"); | System.out.println("\n"); | ||
| Line 34: | Line 38: | ||
| − | + | private static double getNewVelocity(double velocity, double distance) { | |
// If the distance is negative, then change it to be positive and change the sign of the input velocity and the result | // If the distance is negative, then change it to be positive and change the sign of the input velocity and the result | ||
if (distance < 0) { | if (distance < 0) { | ||
| Line 45: | Line 49: | ||
final double speed = Math.abs(velocity); | final double speed = Math.abs(velocity); | ||
| − | // Check if we are decelerating | + | // Check if we are decelerating, i.e. if the velocity is negative. |
| − | if (velocity < 0) { | + | // Note that if the speed is too high due to a new max. velocity, we must also decelerate. |
| + | if (velocity < 0 || speed > currentCommands.getMaxVelocity()) { | ||
// If the velocity is negative, we are decelerating | // If the velocity is negative, we are decelerating | ||
newVelocity = speed - Rules.DECELERATION; | newVelocity = speed - Rules.DECELERATION; | ||
| Line 56: | Line 61: | ||
double accelTime = (1 - decelTime); | double accelTime = (1 - decelTime); | ||
| − | // New velocity (v) = d / t, where time = 1 (i.e. 1 turn). Hence, v = d / 1 => v = d | + | // New velocity (v) = d / t, where time = 1 (i.e. 1 turn). Hence, v = d / 1 => v = d |
| − | newVelocity = Math.min( | + | // However, the new velocity must be limited by the max. velocity |
| − | Rules.DECELERATION * decelTime * decelTime + Rules.ACCELERATION * accelTime * accelTime, distance); | + | newVelocity = Math.min(currentCommands.getMaxVelocity(), |
| + | Math.min(Rules.DECELERATION * decelTime * decelTime + Rules.ACCELERATION * accelTime * accelTime, | ||
| + | distance)); | ||
// Note: We change the sign here due to the sign check later when returning the result | // Note: We change the sign here due to the sign check later when returning the result | ||
| Line 64: | Line 71: | ||
} | } | ||
} else { | } else { | ||
| − | // Else, we are not decelerating | + | // Else, we are not decelerating, but might need to start doing so due to the remaining distance |
// Deceleration time (t) is calculated by: v = a * t => t = v / a | // Deceleration time (t) is calculated by: v = a * t => t = v / a | ||
| Line 84: | Line 91: | ||
if (time <= 1) { | if (time <= 1) { | ||
// When there is only one turn left (t <= 1), we set the speed to match the remaining distance | // When there is only one turn left (t <= 1), we set the speed to match the remaining distance | ||
| − | newVelocity = distance; | + | newVelocity = Math.max(speed - Rules.DECELERATION, distance); |
} else { | } else { | ||
// New velocity (v) = a * t, i.e. deceleration * time | // New velocity (v) = a * t, i.e. deceleration * time | ||
| Line 99: | Line 106: | ||
} | } | ||
} else { | } else { | ||
| − | // Else, we | + | // Else, we need to accelerate, but only to max. velocity |
| − | newVelocity = speed + Rules.ACCELERATION; | + | newVelocity = Math.min(speed + Rules.ACCELERATION, currentCommands.getMaxVelocity()); |
} | } | ||
} | } | ||
| − | |||
| − | |||
| − | |||
// Return the new velocity with the correct sign. We have been working with the speed, which is always positive | // Return the new velocity with the correct sign. We have been working with the speed, which is always positive | ||
return (velocity < 0) ? -newVelocity : newVelocity; | return (velocity < 0) ? -newVelocity : newVelocity; | ||
| − | } | + | } |
| − | |||
| − | |||
} | } | ||
</pre> | </pre> | ||
Revision as of 06:31, 15 July 2009
Some basic code to test 1.7.1.3's updated getNewVelocity() method.
The main class:
import robocode.Rules;
public class VelocityTest {
private static Commands currentCommands = new Commands();
public static void main(String[] args) {
// init
System.out.println("\nDarkcanuck's VelocityTest\n");
if (!args[0].equals("all")) {
testCase(Double.valueOf(args[0]), Double.valueOf(args[1]));
} else {
testCase(0, 6);
}
}
public static void testCase(double velocity, double distance) {
double newvel = velocity;
double newdist = distance;
int tick = 0;
System.out.println("Starting velocity=" + velocity + " distance=" + distance);
while ((Math.abs(newvel)>0.00001) || (Math.abs(newdist)>0.00001)) {
newvel = getNewVelocity(newvel, newdist);
newdist -= newvel;
tick++;
System.out.println(" " + tick + " velocity=" + newvel + " remain=" + newdist);
}
System.out.println("\n");
}
private static double getNewVelocity(double velocity, double distance) {
// If the distance is negative, then change it to be positive and change the sign of the input velocity and the result
if (distance < 0) {
return -getNewVelocity(-velocity, -distance);
}
double newVelocity;
// Get the speed, which is always positive (because it is a scalar)
final double speed = Math.abs(velocity);
// Check if we are decelerating, i.e. if the velocity is negative.
// Note that if the speed is too high due to a new max. velocity, we must also decelerate.
if (velocity < 0 || speed > currentCommands.getMaxVelocity()) {
// If the velocity is negative, we are decelerating
newVelocity = speed - Rules.DECELERATION;
// Check if we are going from deceleration into acceleration
if (newVelocity < 0) {
// If we have decelerated to velocity = 0, then the remaining time must be used for acceleration
double decelTime = speed / Rules.DECELERATION;
double accelTime = (1 - decelTime);
// New velocity (v) = d / t, where time = 1 (i.e. 1 turn). Hence, v = d / 1 => v = d
// However, the new velocity must be limited by the max. velocity
newVelocity = Math.min(currentCommands.getMaxVelocity(),
Math.min(Rules.DECELERATION * decelTime * decelTime + Rules.ACCELERATION * accelTime * accelTime,
distance));
// Note: We change the sign here due to the sign check later when returning the result
velocity *= -1;
}
} else {
// Else, we are not decelerating, but might need to start doing so due to the remaining distance
// Deceleration time (t) is calculated by: v = a * t => t = v / a
final double decelTime = speed / Rules.DECELERATION;
// Deceleration time (d) is calculated by: d = 1/2 a * t^2 + v0 * t + t
// Adding the extra 't' (in the end) is special for Robocode, and v0 is the starting velocity = 0
final double decelDist = 0.5 * Rules.DECELERATION * decelTime * decelTime + decelTime;
// Check if we should start decelerating
if (distance <= decelDist) {
// If the distance < max. deceleration distance, we must decelerate so we hit a distance = 0
// Calculate time left for deceleration to distance = 0
double time = distance / (decelTime + 1); // 1 is added here due to the extra 't' for Robocode
// New velocity (v) = a * t, i.e. deceleration * time, but not greater than the current speed
if (time <= 1) {
// When there is only one turn left (t <= 1), we set the speed to match the remaining distance
newVelocity = Math.max(speed - Rules.DECELERATION, distance);
} else {
// New velocity (v) = a * t, i.e. deceleration * time
newVelocity = time * Rules.DECELERATION;
if (speed < newVelocity) {
// If the speed is less that the new velocity we just calculated, then use the old speed instead
newVelocity = speed;
} else if (speed - newVelocity > Rules.DECELERATION) {
// The deceleration must not exceed the max. deceleration.
// Hence, we limit the velocity to the speed minus the max. deceleration.
newVelocity = speed - Rules.DECELERATION;
}
}
} else {
// Else, we need to accelerate, but only to max. velocity
newVelocity = Math.min(speed + Rules.ACCELERATION, currentCommands.getMaxVelocity());
}
}
// Return the new velocity with the correct sign. We have been working with the speed, which is always positive
return (velocity < 0) ? -newVelocity : newVelocity;
}
}
And a support class for setting the max velocity:
import robocode.Rules;
public class Commands {
private static double maxVelocity = Rules.MAX_VELOCITY;
public static double getMaxVelocity() { return maxVelocity; }
public static void setMaxVelocity(double maxVel) { maxVelocity = maxVel; }
}