Simbad Programming Guide


Home | Download | Docs | Screenshots | SourceForge Summary


Last Modified Sunday 07th 2005f August 2005 10:02

Quick Guide

A quick programming guide for Simbad simulator.

Plan


Create your own robot controller

You need very few things to build and test your own robot controller:

  • a main program.
  • a description of the environment
  • and your robot class

Your main program:

This is your main class and its purpose is to launch Simbad with your environment description. You can just copy the code below and specify the name of your EnvironmentDescription class (here MyEnv).

import simbad.gui.Simbad;
public class MyProg {
    public static void main(String[] args) {
        Simbad frame = new Simbad(new MyEnv() ,false);
    }
}

Your environment description:

Then you need to describe the components of your environment. In the example below we indicate that want only one robot and one Arch (Arch is one of the prebuild objects such as Wall or Box). The robot class MyRobot is the one you provide.

import simbad.sim.*;
import javax.vecmath.Vector3d;
public class MyEnv extends EnvironmentDescription {
    public MyEnv(){
        add(new Arch(new Vector3d(3,0,-3),this));
        add(new MyRobot(new Vector3d(0, 0, 0),"my robot"));
    }
}

Your Robot class:

You may then describe your robot controller with the MyRobot class. MyRobot is derived from the Agent class and you must override the two methods initBehavior and performBehavior.

  • initBehavior is called by the simulator at the very begining of the agent's life and it should initialize the stuff you need (nothing special in the example below).
  • performBehavior is called by the simulator on every simulator step (ie 20 times per second in normal operation).This is where the behavior is described.
import  simbad.sim.*;
import javax.vecmath.Vector3d;

public class MyRobot extends Agent {
    public MyRobot (Vector3d position, String name) {     
        super(position,name);
    }
    public void initBehavior() {}
    
    public void performBehavior() {
        if (collisionDetected()) {
            // stop the robot
            setTranslationalVelocity(0.0);
            setRotationalVelocity(0);
        } else {
            // progress at 0.5 m/s
            setTranslationalVelocity(0.5);
            // frequently change orientation 
            if ((getCounter() % 100)==0) 
               setRotationalVelocity(Math.PI/2 * (0.5 - Math.random()));
        }
    }
}

Compile and run

To compile your program you need to specifiy the directory containing simbad arborescence on the classpath (you can also set your CLASSPATH variable).

javac -classpath simbad-1.0 MyProg.java MyEnv.java MyRobot.java

And you may run the program with the following command:

java -classpath simbad-1.0:. MyProg

up

The simulator

The simulator loop

On each simulation steps the simulator performs the following operations for each agent (robot) alive in the world.

  1. check geometrical collision against other objects.
  2. update the sensors (if any) according to current position and sensor rate.
  3. update the actuators (if any) according to actuator rate.
  4. call user provided method : performBehavior.
  5. update position according to kinematic parameters (translation and rotation velocities by default).

As real devices, sensors and actuators may not be updated on each frame depending on their update rate.

Normal mode

In normal mode (default) the simulation steps are triggered by a timer event 20 times per second. So the real time (seen by the user) and virtual time (seen by each robot) coincide and inter step delay is 1/20=0.05 s. However, the timer can be speeded up or slowed down by intermediary of simbad User interface. If, for instance, the timer is speeded 10 times, the simulator will perform 200 simulation steps per second in real time but from the view point of the robot 10 seconds of virtual time elapse during one second of real time. This enables to preserve time dependant values and units whatever is the real time speed.

Special background mode

For intensive simulations, as often required by Genetic Algorithms and Generate and Test schemes in general, Simbad provides a special background mode. In this mode, the simulation steps are performed at the fastest speed available on your hardware. The 3D world is rendered very rarely for monitoring purpose and use no or very small part of the cpu power. In background mode the user interface inputs are disabled.

Simbad is known to achieve 16000 simulation steps per second on a Pentium 4 PC at 2.8 GHz. Notice however that for the present time only sonars and bumpers are available in this mode. Camera will be available soon in background mode.

import simbad.gui.Simbad;
public class MyProg {
    public static void main(String[] args) {
    	// Launch Simbad in background mode 
        Simbad frame = new Simbad(new MyEnv() ,false);
    }
}

up

The robot API

Status API.

The robot's status can be accessed via the following methods inherited from Agent class.

  • boolean collisionDetected() : returns true if the agent colides an object.
  • int getCounter() : returns the number of simulation steps elapsed.
  • double getOdometer(): returns the agent's odometer in meters.
  • double getLifeTime() : returns the agent total lifetime in virtual seconds.
  • void getCoords(Point3d coord) : returns agents coordinates in meters

Movements API.

You can control the robot movements by specifing rotational and translational velocities.

  • void setRotationalVelocity(double rv) : sets rotational velocity in radians per second.
  • void setTranslationalVelocity(double tv) : sets translational velocity in meters per second.
  • double getRotationalVelocity() : gets rotational velocity in radians per second.
  • double getTranslationalVelocity() : gets translational velocity in meters per second.
  • void moveToStartPosition()  puts the agents back to its start position.

This is the default kinematic model - however you can also use a differential drive kinematic and control left and right wheel velocities. See the demo in class simbad.demo.DifferentialDriveDemo.


up

The Sensors

You can equip your robot with the following sensors:

  • Sonars.
  • Bumpers.
  • Camera
  • light sensor

The RobotFactory class provides methods to easily add sensors.

Adding and using Sonar Sensors

To use sonars you must first add them to the robot. This is done in the Robot constructor and the most simple way is by using the RobotFactory class to obtain a RangeSensorBelt object. The example below adds a 8 sonars belt to the robot, the sonars are organised counter clock wise, starting at angle 0 in front of the robot.

Each sonar provides a range measurement information in meters and a hit state which value is true only if an obstacle is situated on the sonar ray. To access to each sonar sensor individualy you can use hasHit and getMeasurement methods. The example below prints the state of all sonars every 20 frames.


 public class Robot extends Agent {

     RangeSensorBelt sonars;

     public Robot(Vector3d position, String name) {
         super(position, name);
         sonars = RobotFactory.addSonarBeltSensor(this,8);
     }

    public void performBehavior() {
        //every 20 frames
        if (getCounter()%20==0){
            // print each sonars measurement
            for (int i=0;i< sonars.getNumSensors();i++) {
                double range = sonars.getMeasurement(i); 
                double angle = sonars.getAngle(i);
                boolean hit = sonars.hasHit(i);
                System.out.println("Sonar at angle "+ angle +
                "measured range ="+range+ " has hit something:"+hit); 
            }
        }
    }
}

The RangeSensorBelt Class also provide methods for obtaining averaged measurements in the eight angular quadrants around the robot : getFrontQuadrantMeasurement, getFrontLeftQuadrantMeasurement ,getLeftQuadrantMeasurement etc ... More information is given in RangeSensorBelt api doc.

Adding and using Bumpers Sensors

Adding and using Bumbers is very similar to sonars except that we can only use hit information and no range measurement. To use bumpers you must again add them with the RobotFactory class and obtain a RangeSensorBelt object. The example below adds a 8 bumpers belt to the robot, the bumpers are organised counter clock wise, starting at angle 0 in front of the robot.

To access to each bumper sensor individualy you can use hasHit method.The example below prints the state of all bumpers every 20 frames.


 public class Robot extends Agent {

     RangeSensorBelt bumpers;

     public Robot(Vector3d position, String name) {
         super(position, name);
         bumpers = RobotFactory.addBumperBeltSensor(this,8);
   }
    public void performBehavior() {
        //every 20 frames
        if (getCounter()%20==0){
            // print each bumper state 
            for (int i=0;i< bumpers.getNumSensors();i++) {
                double angle = bumpers.getAngle(i);
                boolean hit = bumpers.hasHit(i);
                System.out.println("Bumpers at angle "+ angle 
                + " has hit something:"+hit); 
            }
        }
    }
 }

More information is given in RangeSensorBelt api.


Adding and using a Camera Sensor

Simbad provides a 2D camera sensor which can be settled on the top of the robot (or anywhere else). The 3d world is rendered by the Java3d engine onto the camera image at the desired frequence. The default camera has a 100x100 pixels resolution and a refresh rate of 3 images per second (in virtual time). It can be added by using again the RobotFactory class in the robot constructor. It is also necessary to reserve space for future image capture and this has to be compatible with the actual camera format. To reserve space for a java BufferedImage one may call CameraSensor createCompatibleImage method. One may also obtained a luminance image by calling createCompatibleSensorMatrix to reserve a SensorMatrix object.

To obtain the camera image you have only to call copyVisionImage method and your BufferedImage will be updated. You may then process it as you want with BufferedImage standard API (with getRGB method for instance), you may also use the java advanced imaging framework JAI. However remember that performBehavior is called very frequently (20 times per second by default), so calling copyVisionImage and processing image every frame could be very costly.


 public class Robot extends Agent {

     CameraSensor camera;
     BufferedImage cameraImage;

     public Robot(Vector3d position, String name) {
         super(position, name);
         // add a camera on top of the robot
         camera = RobotFactory.addCameraSensor(this);
         // reserve space for image capture
         cameraImage = camera.createCompatibleImage();
    }

      public void performBehavior() {
           .......  your code

          // get camera image 
          camera.copyVisionImage(cameraImage);
          // process image 
          ... use BufferedImage api
      } 
 }

up

The Actuators

The 3D world

Simbad Project is hosted at SourceForge.net Logo