/*
* Simbad - Robot Simulator
* Copyright (C) 2004 Louis Hugues
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
-----------------------------------------------------------------------------
* $Author: sioulseuguh $
* $Date: 2005/04/25 17:54:59 $
* $Revision: 1.3 $
* $Source: /cvsroot/simbad/src/simbad/sim/KheperaRobot.java,v $
*/
package simbad.sim;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.Material;
import javax.media.j3d.Node;
import javax.media.j3d.Shape3D;
import javax.media.j3d.TriangleArray;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import com.sun.j3d.utils.geometry.Cylinder;
import com.sun.j3d.utils.geometry.Primitive;
/**
* A KheperaRobot Agents. This class provides a prebuild khepera robot with the
* following functionalities:
* <li>8 IR sensors</li>
* <li>Two wheels control</li>
* Note the numbering and angle in degrees of the IR sensors:
* 0 ->+85
* 1 -> +45
* 2 -> +10
* 3 -> -10
* 4 -> -45
* 5 ->-85
* 6 et 7 ->180
*
*
*/
public class KheperaRobot extends Agent {
RangeSensorBelt IRBelt;
/**
* Constructs a new KheperaRobot .
*
* @param pos
* start position.
* @param name
*/
public KheperaRobot(Vector3d pos, String name) {
super(pos, name);
// dimensions
this.height = 0.03f;
this.radius = 0.055f / 2f;
this.mass = 0.07f;
// sensors
addIRSensors();
// two wheels control.
setKinematicModel(new DifferentialKinematic(getRadius()));
}
/**
* Adds the standard set of IR Sensors.
*
*/
private void addIRSensors() {
double pi = Math.PI;
double range = 0.05;
// Angular position of each sensor
double anglesPos[] = { pi / 2 - pi / 8, // 0
pi / 4, // 1
pi / 4 - pi / 6, // 2 front
pi / 4 - pi / 3, // 3 front
-pi / 4, // 4
-pi / 2 + pi / 8, // 5
pi + pi / 8, // 6 back
pi - pi / 8 // 7 back
};
// Orientation of each sensor ray.
double anglesDirs[] = { pi / 2, // 0
pi / 4, // 1
0, // 2 front
0, // 3 front
-pi / 4, // 4
-pi / 2, // 5
pi, // 6 back
pi // 7 back
};
Vector3d pos[] = new Vector3d[8];
Vector3d dirs[] = new Vector3d[8];
// construct positions : relative to belt center
// and direction : relative to sensor pos.
for (int i = 0; i < pos.length; i++) {
double a1 = anglesPos[i];
double a2 = anglesDirs[i];
// Bug corrected : due to z axis inversion must negate sinus
pos[i] = new Vector3d(Math.cos(a1) * radius, 0, -Math.sin(a1)
* radius);
dirs[i] = new Vector3d(Math.cos(a2) * range, 0, -Math.sin(a2)
* range);
}
int flags = RangeSensorBelt.FLAG_SHOW_FULL_SENSOR_RAY;
IRBelt = new RangeSensorBelt(pos, dirs, RangeSensorBelt.TYPE_IR, flags);
IRBelt.setUpdatePerSecond(3);
IRBelt.setName("IR");
Vector3d position = new Vector3d(0, 0, 0.0);
addSensorDevice(IRBelt, position, 0);
}
/** Create 3D geometry. */
protected void create3D() {
Color3f color = new Color3f(0.3f, 0.8f, 0.8f);
Color3f color2 = new Color3f(1.0f, 0.0f, 0.0f);
// body
Appearance appear = new Appearance();
Material mat = new Material();
mat.setDiffuseColor(color);
appear.setMaterial(mat);
int flags = Primitive.GEOMETRY_NOT_SHARED
| Primitive.ENABLE_GEOMETRY_PICKING
| Primitive.GENERATE_NORMALS;
flags |= Primitive.ENABLE_APPEARANCE_MODIFY;
body = new Cylinder(radius, height, flags, appear);
// we must be able to change the pick flag of the agent
body.setCapability(Node.ALLOW_PICKABLE_READ);
body.setCapability(Node.ALLOW_PICKABLE_WRITE);
body.setPickable(true);
body.setCollidable(true);
addChild(body);
// direction indicator
float coords[] = { radius / 2, height, -radius / 2,//
radius / 2, height, radius / 2,//
radius, height, 0 //
};
float normals[] = { 0, 1, 0, 0, 1, 0, 0, 1, 0 };
TriangleArray tris = new TriangleArray(coords.length,
GeometryArray.COORDINATES | GeometryArray.NORMALS);
tris.setCoordinates(0, coords);
tris.setNormals(0, normals);
appear = new Appearance();
appear.setMaterial(new Material(color2, black, color2, white, 100.0f));
Shape3D s = new Shape3D(tris, appear);
s.setPickable(false);
addChild(s);
// Add bounds for interactions and collision
Bounds bounds = new BoundingSphere(new Point3d(0,0,0),radius);
setBounds(bounds);
}
/**
* Returns the set of IR sensor.
*
* @return a RangeSensorBelt.
*/
public RangeSensorBelt getIRSensors() {
return IRBelt;
}
/**
* Sets the wheels velocity.
*
* @param left
* wheel velocity in m/s.
* @param right
* wheel velocity in m/s.
*/
public void setWheelsVelocity(double left, double right) {
((DifferentialKinematic) kinematicModel).setWheelsVelocity(left, right);
}
}