Developer Guide

This guide is a step by step tutorial for developers how to write own graphical simulations using RockOn Fuzzy. RockOn Fuzzy is written in the Java programming language. So we assume in this guide that you have basic skills in Java programming.

Actually it’s not difficult to write an own graphical environment to simulate a special fuzzy control case. In fact only two files have to be created. We demonstrate how to proceed using the pendulum example, which is a core simulation in RockOn Fuzzy.

Summary

To summarize the whole process the following steps have to be performed:

1. Create a new Case file:

This file holds all needed information about the fuzzy controller like:

  • Input and Output variables of the controller
  • The corresponding Simulation file is defined
  • A textual description of the controller
  • Define a signature to ensure that simulation and controller file match
  • Define a default controller file

2. Create a new Simulation file:

In this part the whole graphical interface of the simulation is defined as well as the interaction between simulation and fuzzy controller. The following functionality have to be implemented:

  • The Physical Objects of the simulation (like boxes, spheres, grounds, cars and so on) have to be created
  • Optionally you can add frames to visualize some data or give debug outputs
  • The interaction between your simulation and the corresponding fuzzy controller have to be implemented. To achieve this aim two methods have to be implemented to transmit current sensor data (like angles, velocities etc.) from the simulation to the controller and to handle inputs from the controller which has effects on the simulation (like forces on bodies etc.)

Implementation details

After briefly introducing the different steps we now want to give implementation details. For a clearer understanding we describe the implementation of the ‘Pendulum’ example which is a default simulation in RockOn Fuzzy.
The very first step is to add the Fuzzy Simulation jar file to your projects build path to use our classes.

1. The case file.

We used the class name PendulumCase to describe which controller case we are going to implement. You have to derive your Case File from the SimulationCase class from the de.rockon.fuzzy.simulation.cases package. After adding the abstract methods to implement your skeleton should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import de.rockon.fuzzy.simulation.cases.SimulationCase;
 
public class PendulumCase extends SimulationCase {
	@Override
	public void setDefaultControlFile() {
	}
 
	@Override
	public void setDescription() {
	}
 
	@Override
	public void setSignature() {
	}
 
	@Override
	public void setSimulation() {
	}
 
	@Override
	public void setTitle() {
	}
}

2. The Simulation file.

Corresponding to our case file we preferred the class name PendulumSimulation. This class have to be derived from the abstract class BaseSimulation from the same package. The skeleton of this file should look like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.util.HashMap;
 
import mdes.slick.sui.event.ChangeEvent;
 
import org.newdawn.slick.Graphics;
 
import de.rockon.fuzzy.controller.model.FuzzyVariable;
import de.rockon.fuzzy.simulation.cases.BaseSimulation;
import de.rockon.fuzzy.simulation.cases.SimulationCase;
 
 
public class PendulumSimulation extends BaseSimulation {
 
	public PendulumSimulation(SimulationCase simulationCase) {
		super(simulationCase);
	}
 
	@Override
	protected void drawBackgroundImage(Graphics arg0) {
	}
 
	@Override
	protected void initFrames() {
	}
 
	@Override
	protected void initPhysics() {
	}
 
	@Override
	public void resetFrames() {
	}
 
	public Double getSensorData(FuzzyVariable arg0) {
		return null;
	}
 
	public void handleControllerInput(HashMap<FuzzyVariable , Double> arg0) {
	}
 
	public void stateChanged(ChangeEvent arg0) {
	}
}

Now we start to fill both skeletons with life.

First we implement the PendulumCase class

Define the input and output variables of the controller with final attributes. In our example we have the three inputs angle, velocity and angular velocity of the pendulum. A force on the body is an output variable, which tries to control the trolley in that way that the sphere below the trolley is balanced. Make sure that the string representation of the variables matches the input and output variable names you specified in the Fuzzy rule editor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/** 
Name of the linguistic variable: Angle
*/
public static final String INPUT_ANGLE = "Angle";
 
/** 
Name of the linguistic variable: Velocity 
*/
public static final String INPUT_VELOCITY = "Velocity";
 
/** 
Name of the linguistic variable: Angular Velocity 
*/
public static final String INPUT_ANGULARVELOCITY = "Angular Velocity";
 
/**
Name of the linguistic variable: Force
 */
public static final String OUTPUT_FORCE = "Force";

Define the Signature. Just add your input and output variables encapsulated in a FuzzyVariable object to the signature field like the following. Additionally you have to specify the type of variable (input or output), the unit and the range.
Before starting the simulation with a specified control file the simulator will check if controller and simulation match together to avoid incompatibilities.

1
2
3
4
5
6
7
@Override
public void setSignature() {
	signature.add(new FuzzyVariable(PendulumCase.INPUT_ANGLE, VariableType.INPUT, "Grad", new double[] { -90, 90 }));
	signature.add(new FuzzyVariable(PendulumCase.INPUT_ANGULARVELOCITY, VariableType.INPUT, "Grad/s", new double[] { -90, 90 }));
	signature.add(new FuzzyVariable(PendulumCase.INPUT_VELOCITY, VariableType.INPUT, "km/h", new double[] { -100, 100 }));
	signature.add(new FuzzyVariable(PendulumCase.OUTPUT_FORCE, VariableType.OUTPUT, "Newton", new double[] { -250, 250 }));
}

Set the corresponding simulation file.

1
2
3
4
@Override
public void setSimulation() {
	simulation = new PendulumSimulation(this);
}

1.Some exploratory methods have to be implemented. This information will be displayed in the simulation chooser dialog which is prompted after starting the simulation tool.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Override
public void setTitle() {
	title = "Pendulum Simulation";
}
 
@Override
public void setDescription() {
	this.setDescription("A pendulum which is connected with a flexible body (a trolley). "
			+ "The fuzzy control tries to balance the pendulum by forcing " + "the trolley in horizontal direction.\n\n"
			+ "Input : angle, velocity and angular velocity\n" + "Output: force on the trolley");
}
 
@Override
public void setDefaultControlFile() {
	defaultControlFile = "C:\Control_files\Pendulum.fxml";
}
 
@Override
public void setPreviewImagePath() {
	previewImagePath = "C:\images\pendulum.png";
}

This was all about the case file.

In the next step we are going to implement the simulation itself

This is a bit costlier but not difficult at all :)

We start implementing the initPhysics() method. All objects in the world like the ground, cars, spheres and so on are defined in this method. For this purpose we use the Phys2D physics engine. It’s beyond the scope of this tutorial to give a complete insight to that library. You can find some nice examples and tutorials here. We used the Slick Game library to draw all the objects in the simulation. You can find details on this library here. In our example simulation the trolley and the ground are implemented using these two libraries. Do not forget to add you self created objects to the world object. Our method looks like this:

1
2
3
4
5
6
7
@Override
protected void initPhysics() {
	ground = new Ground(screenWidth / 2, (screenHeight / 2), screenWidth * 2, groundHeight, gameContainer);
	trolley = new Trolley(screenWidth / 2, screenHeight / 2 - 50, Trolley.DOWN_MODE, screenWidth, gameContainer);
	world.add(ground);
	world.add(trolley);
}

You have to implement the getSensorData() method to enable the fuzzy controller acquire actual values for your input variables. In our case this method provides actual data for the three controller input variables angular, velocity and angular velocity of the pendulum. In the function signature the controller specifies which sensor to query.

1
2
3
4
5
6
7
8
9
10
11
@Override
public Double getSensorData(FuzzyVariable inputVariable) {
	if (inputVariable.getName().equals(PendulumCase.INPUT_ANGLE)) {
		return currentAngle;
	} else if (inputVariable.getName().equals(PendulumCase.INPUT_ANGULARVELOCITY)) {
		return currentAnglularVelocity;
	} else if (inputVariable.getName().equals(PendulumCase.INPUT_VELOCITY)) {
		return currentVelocity;
	}
	return null;
}

On the other hand the simulation must react on inputs from the controller. In our case this would be a force on the trolley to get the sphere balanced. To achieve this aim you have to implement the handleControllerInput() method. A map of all output values from the controller is given to the method as a parameter. The physical objects in our simulation world have to react on these values. In Our case we provide a force on our trolley in the following way:

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public void handleControllerInput(HashMap< FuzzyVariable , Double> input) {
	if (fuzzy) {
		for (Entry< FuzzyVariable , Double > entry : input.entrySet()) {			
			if (entry.getKey().getName().equals(PendulumCase.OUTPUT_FORCE)) {
				System.out.println("Force: " + entry.getValue() + " " + entry.getKey().getUnit());
				trolley.setForce(entry.getValue());
				trolley.driveFuzzy();
			}
		}
	}
}

Some extra Features

… to be continued in near future.

Open tasks:

  • How to add frames to your simulation
  • Explain Phys2D and Slick more detailed using our trolley example
These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • Digg
  • Furl
  • Webnews
  • MisterWong
  • Y!GG
  • Google Bookmarks
  • Linkarena
  • Folkd
  • Bloglines
  • Linkarchiv
  • YahooMyWeb
  • Slashdot
  • Ma.gnolia
  • Blue Dot
  • blogmarks