Darkcanuck/VelocityTest

From Robowiki
< Darkcanuck
Revision as of 05:55, 15 July 2009 by Darkcanuck (talk | contribs) (testing getNewVelocity)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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("Darkcanuck's VelocityTest\n\n");
        
        testCase(Double.valueOf(args[0]), Double.valueOf(args[1]));
    }
    
    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 + "\n");
        while (newdist > 0.0) {
            newvel = getNewVelocity(newvel, newdist);
            newdist -= newvel;
            tick++;
            System.out.println("  " + tick + " velocity=" + newvel + " remain=" + newdist+"\n");
        }
        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
		if (velocity < 0) {
			// 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 
				newVelocity = 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. Perhaps we should decelerate? If not, we should accelerate instead

			// 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 = 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 are accelerating
				newVelocity = speed + Rules.ACCELERATION;
			}
		}

		// 0 <= velocity <= max. velocity
		newVelocity = Math.min(currentCommands.getMaxVelocity(), Math.abs(newVelocity));

		// 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; }
}