User:Pedersen/Code Samples/Radar
Jump to navigation
Jump to search
package pedersen.systems;
I have developed three modes of radar operation, used under various circumstances.
- Passive Mode: sweeps a tiny arc forward of the tank.
- Duel Mode: sweeps full circle until a target is aquired, then locks on the target with a rather small arc, which scales to the distance from the enemy.
- Melee Mode: sweeps full circle until a target is aquired, temporarily locking on the target in a wide arc, and periodically circle sweeping afteward.
The three share an interface and a base class.
/** * Common interface for all scanning methods. */ public interface ScanningMethod { //::////////////////////////////////////// //:: Methods //::////////////////////////////////////// /** * Operates the scanner. * * @param absoluteHeading the present scanner heading * @param projectedPosition the projected scanner position * @param target the present target lock * * @return the relative heading change as a result of the operation */ public double operate( double absoluteHeading, Vehicle projectedPosition, Target target ); //::////////////////////////////////////// //:: Static Constants //::////////////////////////////////////// public static final double maximumRateOfRelativeRotation = Math.PI / 4.0; // 45 degrees } /** * Common base class for all scanning methods. */ public class ScanningMethodBase { //::////////////////////////////////////// //:: Methods //::////////////////////////////////////// /** * Instructs a scanner to move to an angle offset beyond a heading. * Subsequent scans flip to the other side of the heading. * * @param scanner the scanner to instruct * @param heading the mean scan heading * @param sweepAngle the angle to sweep to either side of the mean scan heading */ protected void sweep( DynamicHeading scanner, double heading, double sweepAngle ) { scanner.setAbsoluteTargetHeading( heading + ( sweepAngle * ( -0.5 + scanIndex % 2 ) ) ); } //::////////////////////////////////////// //:: Instance Variables //::////////////////////////////////////// protected static long scanIndex = 0; } /** * Scanning Methods for locking onto a target until it is destroyed. * Until a target is aquired, the scanner sweeps clockwise indefinitely. */ public class ScanningMethodLockImpl extends ScanningMethodBase implements ScanningMethod { //::////////////////////////////////////// //:: Methods //::////////////////////////////////////// /** * Operates the scanner. * * @param absoluteHeading the present scanner heading * @param projectedPosition the projected scanner position * @param target the present target lock * @return the relative heading change as a result of the operation */ public double operate( double absoluteHeading, Vehicle projectedPosition, Target target ) { DynamicHeading scanner = new DynamicHeadingImpl( maximumRateOfRelativeRotation ); scanner.setHeading( absoluteHeading ); scanIndex++; if( target == null ) { scanner.setRelativeTargetHeading( maximumRateOfRelativeRotation ); } else { double targetScanNarrow = 2.0 * Math.atan( Vehicle.maximumAbsVelocity / projectedPosition.getDistance( target ) ); this.sweep( scanner, projectedPosition.getBearing( target ).getHeading(), targetScanNarrow ); } return scanner.compare( new StaticHeadingImpl( scanner.projectHeading() ) ); } } /** * Scanning Methods for sweeping a tiny arc to the front. * This is fluff radar mode for end of round victory dances, etc. */ public class ScanningMethodPassiveImpl extends ScanningMethodBase implements ScanningMethod { //::////////////////////////////////////// //:: Methods //::////////////////////////////////////// /** * Operates the scanner. * * @param absoluteHeading the present scanner heading * @param projectedPosition the projected scanner position * @param target the present target lock * @return the relative heading change as a result of the operation */ public double operate( double absoluteHeading, Vehicle projectedPosition, Target target ) { DynamicHeading scanner = new DynamicHeadingImpl( maximumRateOfRelativeRotation ); scanner.setHeading( absoluteHeading ); scanIndex++; this.sweep( scanner, projectedPosition.getHeading(), targetScanOff ); return scanner.compare( new StaticHeadingImpl( scanner.projectHeading() ) ); } //::////////////////////////////////////// //:: Static Constants //::////////////////////////////////////// private static final double targetScanOff = 0.00001; } /** * Scanning Methods for situational awareness. * Until a target is aquired, the scanner sweeps clockwise indefinitely. * After a target is aquired, the scanner is semi-locked in a wide arc, periodically rescanning the environment. */ public class ScanningMethodStandardImpl extends ScanningMethodBase implements ScanningMethod { //::////////////////////////////////////// //:: Methods //::////////////////////////////////////// /** * Operates the scanner. * * @param absoluteHeading the present scanner heading * @param projectedPosition the projected scanner position * @param target the present target lock * @return the relative heading change as a result of the operation */ public double operate( double absoluteHeading, Vehicle projectedPosition, Target target ) { DynamicHeading scanner = new DynamicHeadingImpl( maximumRateOfRelativeRotation ); scanner.setHeading( absoluteHeading ); if( scanIndex++ > scanCycle) this.resetScanCycle( ); if( ( target == null ) || ( scanIndex < scanSweepCycle ) ) { scanner.setRelativeTargetHeading( maximumRateOfRelativeRotation ); } else { this.sweep( scanner, projectedPosition.getBearing( target ).getHeading(), targetScanWide ); } return scanner.compare( new StaticHeadingImpl( scanner.projectHeading() ) ); } /** * Resets the scan cycle index, forcing an immediate sweep and a fresh delay for the recurring sweep. */ private void resetScanCycle( ) { scanIndex = 0; } //::////////////////////////////////////// //:: Static Constants //::////////////////////////////////////// private static final double targetScanWide = maximumRateOfRelativeRotation; private static final long scanSweepCycle = 8; private static final long scanCycle = 40; }
The scan cycle reset method could be moved into the base class and exposed through the interface so that it can be called when taking an actual shot.