/* * 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/08/07 12:24:56 $ * $Revision: 1.17 $ * $Source: /cvsroot/simbad/src/simbad/sim/Agent.java,v $ * - AGent no more derived from CollidableObject */ package simbad.sim; import java.text.DecimalFormat; import javax.media.j3d.Appearance; import javax.media.j3d.Material; import javax.media.j3d.Node; import javax.media.j3d.Shape3D; import javax.media.j3d.*; import javax.swing.JInternalFrame; import javax.swing.JPanel; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import simbad.gui.AgentInspector; import com.sun.j3d.utils.geometry.*; /** * This is the base class for all robot and is considered to be a heavy agent. <br> * When deriving a new robot's class from this class, one should override the following methods: * <ul> * <li> initBehavior : called by the simulator to initialize the controler.</li> * <li> performBehavior : called by the simulator on each simulation step.</li> * </ul> * * Implementation note : the agent doesnt have synchronized methods. * All thread refering to the agent should do explicit synchronization with synchronized(agent){...}. * */ public class Agent extends SimpleAgent { /** panel dedicated to behavior output - can be null. */ private JPanel panel; /** window dedicated to behavior output - can be null. */ JInternalFrame window; /** Link back to agent inspector - can be null */ AgentInspector agentInspector; /** Kinematic model used by the agent*/ protected KinematicModel kinematicModel; /** Current linear acceleration applied by motors. */ protected Vector3d motorsLinearAcceleration = new Vector3d(); /** Current angular acceleration applied by motors..*/ protected Vector3d motorsAngularAcceleration = new Vector3d(); private DecimalFormat format; /** Used for frame rate measure */ protected FrameMeter frameMeter; /** * Constructs an Agent. * @param pos start position in 3D world. * @param name name of the agent. */ public Agent(Vector3d pos, String name) { super(pos, name); // No UI by default this.panel = null; agentInspector = null; // physical parameters default height = 0.5f; radius = 0.3f; staticFrictionCoefficient = 0; mass = 50; // display format for numbers format = new DecimalFormat(); format.setMaximumFractionDigits(3); format.setMinimumFractionDigits(3); format.setPositivePrefix("+"); format.setMinimumIntegerDigits(1); // Attached a default kinematic kinematicModel = new DefaultKinematic(); // Performance measure frameMeter = new FrameMeter(); } /** Resets agent variables */ protected void reset(){ super.reset(); frameMeter.reset(); } /** Resets agent variables and position and kinematic */ protected void resetPosition(){ super.resetPosition(); kinematicModel.reset(); } /** Create 3D geometry. */ protected void create3D(){ Color3f color = new Color3f(0.0f,0.8f,0.0f); Color3f color2 = new Color3f(1.0f,0.0f,0.0f); // body Appearance appear = new Appearance(); color.clampMax(0.8f); material.setDiffuseColor(color); material.setSpecularColor(black); appear.setMaterial(material); 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); /* // allow geom intersect on each geom of the primitive cylinder allowIntersect(body.getShape(Cylinder.BODY)); allowIntersect(body.getShape(Cylinder.TOP));*/ // 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); } /** set acceleration applied by motors .*/ protected void setMotorsAcceleration(double dt) { // TODO CHange this !!! linearVelocity.set(0,0,0); angularVelocity.set(0,0,0); kinematicModel .update(dt, rotation, instantTranslation, instantRotation); // derive two times displacement to obtain acceleration double scale = 1.0 /(dt*dt);// dt non zero motorsLinearAcceleration.set(instantTranslation); motorsLinearAcceleration.scale(scale); motorsAngularAcceleration.set(instantRotation); motorsAngularAcceleration.scale(scale); // contribute to general acceleration linearAcceleration.set(motorsLinearAcceleration); angularAcceleration.set(motorsAngularAcceleration); } /** called by simulator. */ protected void initPreBehavior() { // if there's a ui window show it if (window != null) window.toFront(); } /** called by simulator. */ protected void initBehavior() { } /** called by simulator. */ protected void performPreBehavior() { frameMeter.measurePoint(1); } /** called by simulator. */ protected void performBehavior() {} /** * Returns the agent's odometer in meters. * @return the agent odometer in meters. */ public double getOdometer(){ return odometer; } /** * Sets rotational velocity in radians per second. */ public final void setRotationalVelocity(double rv) { // because it's one of the default kinematic fucntions we provide it in the // agent's api. if (kinematicModel instanceof DefaultKinematic) ((DefaultKinematic)kinematicModel).setRotationalVelocity(rv); } /** * Sets translational velocity in meter per second. */ public final void setTranslationalVelocity(double tv) { // because it's one of the default kinematic fucntions we provide it in the // agent's api. if (kinematicModel instanceof DefaultKinematic) ((DefaultKinematic)kinematicModel).setTranslationalVelocity(tv); } /** * Gets rotational velocity in radians per second */ public final double getRotationalVelocity() { // because it's one of the default kinematic fucntions we provide it in the // agent's api. if (kinematicModel instanceof DefaultKinematic) return ((DefaultKinematic)kinematicModel).getRotationalVelocity(); else return 0.0; } /** * Gets translational velocity in meter per second. */ public final double getTranslationalVelocity() { // agent's api. if (kinematicModel instanceof DefaultKinematic) return ((DefaultKinematic)kinematicModel).getTranslationalVelocity(); else return 0.0; } /** Sets the kinematic model for this agent */ protected void setKinematicModel(KinematicModel kinematicModel){ this.kinematicModel = kinematicModel; } protected KinematicModel getKinematicModel(){ return kinematicModel; } protected void setFrameMeterRate(int rate){ frameMeter.setUpdateRate(rate); } /** * Add a UI panel to the agent. Typically used for displaying behavior outputs. * A call to this method will have for consequence the creation of a dedicated window. * @param panel */ public void setUIPanel(JPanel panel){ this.panel = panel; } /** * Returns the UI panel previously set with <code>setUIPanel</code> * @return the panel */ public JPanel getUIPanel(){ return panel; } /** Creates the UI that may be associated to the agent. * If the agent has set a Panel with setUIPanel a window is created containing the panel. * */ JInternalFrame createUIWindow(){ JPanel panel = getUIPanel(); if (panel!=null){ window = new JInternalFrame("Output",false,false,false,false); window.setContentPane(panel); window.pack(); } else window = null; return window; } public AgentInspector getAgentInspector(){ return agentInspector ; } public void setAgentInspector(AgentInspector ai){ agentInspector = ai; } /** Dispose all resources */ protected void dispose(){ if (window != null) window.dispose(); } /** * Returns printable description of the agent. * @return agent description as string. */ public String asString(){ String s = new String(); Vector3d t = v1; translation.get(t); s= "class = " + this.getClass().getName() + "\n" + "name \t= " + name + "\n" + "fps instant \t= " + format.format(frameMeter.fps) + "\n"+ "fps total \t= " +format.format(frameMeter.fpsSinceStart) +"\n" + "counter \t= " + getCounter() + "\n" + "lifetime \t= " + format.format(getLifeTime()) + " s\n" + "collision \t= " + this.collisionDetected+ "\n" + // "interaction \t= " + this.interactionDetected+ "\n" + kinematicModel.toString(format) + "x \t= " + format.format(t.x) + " m\n" + "y \t= " + format.format(t.y) + " m\n" + "z \t= " + format.format(t.z) + " m\n"+ "odometer \t= " + format.format(odometer) + " m\n"; return s; } }