My Works

Robot Movement(Java)

Here we are going to look at achieving robot actions by moving and turning a simple image on the Grid panel.The image is positioned (0, 0) coordinates is at Lower Left rather than the usual upper left of the Grid Panel.The command for movements actions and turns are given from the command line and the packaging is executable jar with dependencies. Some of the brief points that need to be done are...

  1. (0, 0) coordinate axis points starting from lower left.
  2. Draw Grid Lines vertical and horizontal with say spacing of 50.
  3. Loading a buffered image given a path.
  4. Rotating the Image to the given angle.
  5. Define Robot, TurningRobot classes and other related and utility classes and interfaces.
  6. POM file.
  7. Add Relative movements.
  8. If you think it is too much to go through and a Download of worked example would help, Download Here.

Before we proceed: To start with. We have a class called Robot with X, Y coordinate values as variables which are used to define movement in North, East, West and South. Thereby we have subclass TurningRobot which overrides Robot movement methods and also adds its own methods. TurningRobot object also has an image associated.This image movements and Rotation on the Grid Panel is what we are going to look at.This is to give an understanding of the objects that we will be referring below.

1. To achieve (0, 0) coordinates starting from lower left.

Normally the (x, y) coordinate system for (0, 0) is at the upper left. We have chosen to achieve (0, 0) coordinate system from the lower left.To achieve this we got to rotate the panel 270 degrees. However here you have to consider changing the mapped directions.Like say moving north or South you are changing the x coordinate and moving East or West you are changing the y coordinate.

		
	public static final int GRIDPANEL_ROTATED_TO_DEGREES_270 = 270;
	//turning the JPanel 270 degrees
	private void turnPanel270Degrees(Graphics g, int frameWidth, int frameHeight, JPanel panel) 
	{
		Graphics2D g2d = (Graphics2D) g;
		int width = frameWidth / 2;
		int hieght = frameHeight / 2;
		g2d.rotate(Math.toRadians(GRIDPANEL_ROTATED_TO_DEGREES_270), width, hieght);
		panel.paintComponents(g);
	}
	
	

2. Now draw Grid Lines vertical and Horizontal with say spacing of 50

		
	public static final int SPACING_BETWEEN_GRID_LINES_50 = 50;
	
	private void drawGridLines(Graphics g, int frameWidth, int frameHeight, int point) {
		// vertical grid lines 
		while (point < frameWidth) {
			point = point + SPACING_BETWEEN_GRID_LINES_50;
			g.drawLine(point, 0, point, frameHeight);
		}
		point = 0;
		// horizontal grid lines		
		while (point < frameHeight) {
			point = point + SPACING_BETWEEN_GRID_LINES_50;
			g.drawLine(0, point, frameWidth, point);
		}
	}
	
	

3. Loading a buffered image given a path involves creating an image and converting to an instance of buffered image.

		
	public class RobotImageUtility {

	private static final Logger logger = Logger.getLogger(RobotImageUtility.class);
		
	public static BufferedImage create(String path) {
		java.net.URL imageURL = null;
		BufferedImage bufferedImage = null;
		try {
			imageURL = RobotImageUtility.class.getResource(path);
			logger.info(LOGGER_TEXT_IMAGE_URL_IS + SPACE + imageURL.getPath());
		} catch (Exception e) {
			logger.info(LOGGER_TEXT_IMAGE_PATH_IS_NOT_VALID + SPACE + path + SPACE + e.getMessage());
		}
		Image icon = null;
		if (imageURL != null ) {
			icon = new ImageIcon(imageURL).getImage();			
			bufferedImage = toBufferedImage(icon);			
		}
		return  bufferedImage;
	}
	
	public static BufferedImage toBufferedImage(Image providedImage) {
		BufferedImage bufferedImage = null;
		if (providedImage instanceof BufferedImage) {
			return (BufferedImage) providedImage;
		}

		if ((providedImage.getWidth(null) <= 0) || (providedImage.getHeight(null) <= 0)) {

			InvalidBufferedImage(EMPTY);
		} else {			
			bufferedImage = new BufferedImage(providedImage.getWidth(null), providedImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
			// Draw the image on to the buffered image
			Graphics2D bGr = bufferedImage.createGraphics();
			bGr.drawImage(providedImage, 0, 0, null);
			bGr.dispose();			
		}

		return bufferedImage;
	}
	
	private static BufferedImage InvalidBufferedImage(String path) {
		logger.info(LOGGER_TEXT_IMAGE_PATH_IS_NOT_VALID + SPACE + path);
		return null;
	}

}
	
	

4. Rotating the Image to the given angle.

AfflineTransform helps in changing the 2D coordinate mapping and rotate the image on its head, yet maintaining the "straightness" and "parallelness" of line. Furthermore here..

		
private void rotatePlaceImage(Graphics g, TurningRobot turningRobot) {
		BufferedImage image = null;
		try {		
			image =  RobotImageUtility.create(turningRobot.getRobotImage().getImageLocation());			
		} catch (Exception e) {
			
			turningRobot.getMovementErrors().addToErrors("Error");
		}

		if (image != null) {
			AffineTransform transform = new AffineTransform();
		   // In the Example provided for Download the Image width and Height  has been varied to avoid cropping of image upon rotation
			transform.rotate(Math.toRadians(turningRobot.getAngle()), image.getWidth() / 2, image.getHeight() / 2);
			AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
			image = op.filter(image, null);

			g.drawImage(image, turningRobot.getRobotImage().getImageXPosition(), turningRobot.getRobotImage().getImageYPosition(), null);
			
		}
}
	
	
VisualGrid With Image

5. Define Robot, TurningRobot classes and other related and utility classes and interfaces.

Now the easiest bit is Create class Robot with variables int x, int y representing the coordinates.Provide the methods representing movement North is y = y + 1;, movement South y = y - 1; movement east is x = x + 1; and movement West is x = x - 1;. Once you the done the above Robot Class, Now override the usual flow to suit our situation. If you think creating Robot class is unnecessary then put the movements directly to the Turning Robot class. Also set a variable for rotating angle in the class for Turning Robot.

		
//override the Robot methods.
	
		public void moveNorth() {
		int previousXValue = getX();
		int x = getX() + 1;
         ............
		 .........
     }
	 
	 
	 public void moveSouth() {
		int previousXValue = getX();
		int x = getX() - 1;
		.............
		............
	}
	
	public void moveEast() {
		int previousYValue = getY();
		int y = getY() + 1;
		............
		............
	}
	
	public void moveWest() {
		int previousYValue = getY();
		int y = getY() - 1;
		..........
		..........
	}

	
	

With the above provided movement by North,East,South and West we can now determine the movements based on angle of rotation.Here we are assuming that every Turn is 90 degrees.

		
public void movementDirection(TurningRobot turningRobot, Movement movement) {
		switch (movement) {
		case FORWARD:
			if (turningRobot.getAngle() == ROTATING_ANGLE_0 || turningRobot.getAngle() == ROTATING_ANGLE_360) {
				moveNorth();
			} else if (turningRobot.getAngle() == ROTATING_ANGLE_90) {

				moveEast();
			} else if (turningRobot.getAngle() == ROTATING_ANGLE_180) {
				moveSouth();
			} else if (turningRobot.getAngle() == ROTATING_ANGLE_270) {
				moveWest();
			}

			break;
		case BACKWARD:
			if (turningRobot.getAngle() == ROTATING_ANGLE_0 || turningRobot.getAngle() == ROTATING_ANGLE_360) {
				moveSouth();
			} else if (turningRobot.getAngle() == ROTATING_ANGLE_90) {

				moveWest();
			} else if (turningRobot.getAngle() == ROTATING_ANGLE_180) {
				moveNorth();
			} else if (turningRobot.getAngle() == ROTATING_ANGLE_270) {
				moveEast();
			}
			break;
		default:
			logger.info(EXCEPTION_TEXT_UNKNOW_MOVEMENT_DIRECTION + SPACE + movement);
			throw new RuntimeException(EXCEPTION_TEXT_UNKNOW_MOVEMENT_DIRECTION + SPACE + movement);

		}
	}
	
	

Now that movements are available, it is time to determine the Turns Left and Right. All we are going to do here is determine the angle for a left or right command.This would be picked up by rotatePlaceImage(Graphics g, TurningRobot turningRobot) method in the TurningRobotHandler class.

		
	public static int determineRotationAngle(TurningRobot turningRobot, Orientation turn) {
		int angle = 0;
		logger.info(LOGGER_TEXT_ANGLE_BEFORE_DETERMINE_ROTATION_ANGLE_WAS + SPACE + turningRobot.getAngle());

		if (Orientation.LEFT.equals(turn)) {

			angle = (turningRobot.getAngle() == ROTATING_ANGLE_0) ? ROTATING_ANGLE_270 : turningRobot.getAngle() - ROTATING_ANGLE_90;

		} else {
			angle = (turningRobot.getAngle() == ROTATING_ANGLE_360) ? ROTATING_ANGLE_90 : turningRobot.getAngle() + ROTATING_ANGLE_90;
		}
		turningRobot.setAngle(angle);		
		return angle;
	}

	
	
Turns and Movements

6. To build it as Executable, The POM file Dependencies

		
<properties>

		<log4j.version>1.2.17</log4j.version>
	</properties>
	
	<dependencies>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.8.1</version>
		</dependency>

		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>${log4j.version}</version>
		</dependency>

	</dependencies>

	
	

Packing using the maven plugins...

		
	<build>
		<finalName>TurningMovingImage</finalName>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-assembly-plugin</artifactId>
				<version>2.4</version>
				<executions>
					<execution>
						<goals>
							<goal>attached</goal>
						</goals>
						<phase>package</phase>
						<configuration>
							<descriptorRefs>
								<descriptorRef>jar-with-dependencies</descriptorRef>
							</descriptorRefs>
							<archive>
								<manifest>
									<mainClass>org.srinivas.siteworks.visual.VisualGrid</mainClass>
								</manifest>
							</archive>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
	
	

7. Add Relative movements.

Now that we have movements and turns,we can extend the Robot or TurniningRobot and move the Robot image relatively.In the sense one move in any directions is equals to 50 moves for the image thus making it more extensible. Also you can have number of robots with different relative movements to their images.That's it. Please do check the worked out example.