Difference between revisions of "Darkcanuck/VelocityTest"

From Robowiki
Jump to navigation Jump to search
(testing getNewVelocity)
 
(uses right version now...)
Line 13: Line 13:
 
          
 
          
 
         // init
 
         // init
         System.out.println("Darkcanuck's VelocityTest\n\n");
+
         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 + "\n");
+
         System.out.println("Starting velocity=" + velocity + " distance=" + distance);
         while (newdist > 0.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+"\n");
+
             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) {
+
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. Perhaps we should decelerate? If not, we should accelerate instead
+
// 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 are accelerating
+
// Else, we need to accelerate, but only to max. velocity
newVelocity = speed + Rules.ACCELERATION;
+
newVelocity = Math.min(speed + Rules.ACCELERATION, currentCommands.getMaxVelocity());
 
}
 
}
 
}
 
}
 
// 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 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; }
}