package AP2DX.motor;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.lang.Math;
import AP2DX.*;
import AP2DX.specializedMessages.*;
/**
* This module translates commands such as "drive forward 1 metre" to something
* the coordinator can send (almost directly) to the USAR sim.
*
* To "know" when the robot has moved X metres is tricky. Currently the odometry
* sensor data is used. This is the x and y position relative to the start
* position. When we want to move Z metres we simply interpolate the distance
* from different odometry data and calculate the distance travelled.
*
* For turns we might be able to use the last argument of the odometry data.
*
* @author Wadie Assal
* @author Maarten Inja
*/
public class Program extends AP2DXBase {
/**
* The distance (measured in ???) since the last odometry data was received.
*/
private double deltaDistanceSinceLastCommand = 0;
/** The distance to travel. */
private double distanceAim = 0;
// /** The amount of meters we want to drive forward or backward. The
// * x-axis is the axis paralel to the forward and backward moving
// direction.
// * See figure 18 "SAE J670 Vehicle Coordinate System" of the USAR sim
// manual.
// * Negative simply means moving backward. */
// private double xAxisAim = 0;
// /** The amount of degrees we want to turn left or right. See figure 18
// * "SAE J670 Vehicle Coordiante System" of the USAR sim manual. Negative
// * means 'rotating' (or rather turning) left. */
// private double yawAim = 0;
/** Used to calculate if we have already moved a distance or not. */
private double lastOdometryX = 0;
/** Used to calculate if we have already moved a distance or not. */
private double lastOdometryY = 0;
/**
* Entry point of motor.
*/
public static void main(String[] args) {
new Program();
}
/**
* Constructor of the motor program
*/
public Program() {
super(Module.MOTOR); // explicitly calls base constructor
System.out.println("Running Motor... ");
}
/**
*
* This module receives a "motor action message" from the reflex module and
* sends "motor messages" to the coordinator. The messages received will
* contain information such as "forward 1 meter" or "left 30 degrees".
*
* This modules task is to send messages to the coordinator to make the
* robot drive. To send messages with a delay seems like a terrible idea
* because these messages could be become unwanted (for example when new
* commands have been given.
*
*/
public ArrayList<AP2DXMessage> componentLogic(Message message) {
ArrayList<AP2DXMessage> messageList = new ArrayList<AP2DXMessage>();
System.out.println("Motor received message: "
+ message.getMessageString());
switch (message.getMsgType()) {
case AP2DX_MOTOR_ACTION:
doMotorActionLogic(new ActionMotorMessage((AP2DXMessage) message),
messageList);
break;
case AP2DX_SENSOR_INS:
doOdometryLogic((OdometrySensorMessage) message, messageList);
break;
default:
System.out
.println("Unexpected message type in ap2dx.motor.Program: "
+ message.getMsgType());
}
return messageList;
}
/**
* Processes an odometry sensor message and adds new messages to the second
* argument if necessary.
*/
private void doOdometryLogic(OdometrySensorMessage odometrySensorMessage,
ArrayList<AP2DXMessage> messageList) {
double odometryX = odometrySensorMessage.getX();
double odometryY = odometrySensorMessage.getY();
// linear interpolation to calculate how much the robot has travelled
double deltaX = odometryX - lastOdometryX;
double deltaY = odometryY - lastOdometryY;
deltaDistanceSinceLastCommand += Math.sqrt(deltaX * deltaX + deltaY
* deltaY);
lastOdometryX = odometryX;
lastOdometryY = odometryY;
// if we've traveled enough, STOP!
if (deltaDistanceSinceLastCommand >= distanceAim)
messageList.add(new MotorMessage(IAM, Module.COORDINATOR, 0, 0));
} // }}}
/**
* Processes a motor action message and adds new messages to the second
* argument if necessary. {{{
*/
private void doMotorActionLogic(ActionMotorMessage actionMotorMessage,
ArrayList<AP2DXMessage> messageList) {
ActionMotorMessage.ActionType action = actionMotorMessage
.getActionType();
switch (action) {
case FORWARD:
// deltaDistanceSinceLastCommand = 0;
double speed = actionMotorMessage.getValue();
AP2DXMessage fwMsg = new MotorMessage(IAM, Module.COORDINATOR,
speed, speed);
fwMsg.setDelay(this.getLastDelay());
messageList.add(fwMsg);
break;
case BACKWARD:
// return motor.backward(actionMotorMessage.getValue());
// deltaDistanceSinceLastCommand = 0;
double speedb = actionMotorMessage.getValue();
AP2DXMessage bwMsg = new MotorMessage(IAM, Module.COORDINATOR,
-speedb, -speedb);
bwMsg.setDelay(this.getLastDelay());
messageList.add(bwMsg);
break;
case TURN:
// return motor.turn(actionMotorMessage.getValue());
double direction = actionMotorMessage.getValue();
if (direction < 0) {
AP2DXMessage tlMsg = new MotorMessage(IAM, Module.COORDINATOR,
-2, 2);
tlMsg.setDelay(this.getLastDelay());
messageList.add(tlMsg);
} else if (direction > 0) {
AP2DXMessage trMsg = new MotorMessage(IAM, Module.COORDINATOR,
2, -2);
trMsg.setDelay(this.getLastDelay());
messageList.add(trMsg);
}
break;
case STOP:
// return motor.stop();
messageList.add(new MotorMessage(IAM, Module.COORDINATOR, 0, 0));
break;
default:
System.out.println("Error in motor.program.componentlogic");
}
// messageList.add(sonarSensorMessage);
} // }}}
}