package com.roboclub.robobuggy.simulation;
import com.roboclub.robobuggy.main.Util;
import com.roboclub.robobuggy.messages.GPSPoseMessage;
import com.roboclub.robobuggy.ros.NodeChannel;
import com.roboclub.robobuggy.ros.Publisher;
import java.util.Date;
import java.util.TimerTask;
/**
* @author Trevor Decker
* <p>
* The controller class for tracking how the buggy actually hidden state allowing for simulated
* sensors to receive information
* y is latitude, x is longitude
*/
public final class SimulatedBuggy {
private static SimulatedBuggy instance;
private boolean brakesDown = false;
private Publisher simPosePub = new Publisher(NodeChannel.SIM_POSE.getMsgPath());
/**
* @return the brakesDown
*/
public boolean isBrakesDown() {
return brakesDown;
}
/**
* @param brakesDown the brakesDown to set
*/
public void setBrakesDown(boolean brakesDown) {
this.brakesDown = brakesDown;
}
private double x = 0.0;
private double y = 0.0;
private double th = 0.0;
private double wheelTh = 0.0;//the orintation in buggy coordinates of the front wheel
private double desiredWheelTh = 0.0;
private double dx = 0.0;
private double dy = 0.0;
private long lastUpdateTime;
/**
* @return a reference to the simulated buggy
*/
public static synchronized SimulatedBuggy getInstance() {
if (instance == null) {
instance = new SimulatedBuggy();
}
return instance;
}
/**
* Constructor for the simulated buggy
*/
private SimulatedBuggy() {
//set init values
x = 0.0;
y = 0.0;
th = 0.0; //in degrees
dx = 0.0;
dy = 0.0;
lastUpdateTime = new Date().getTime();
java.util.Timer t = new java.util.Timer();
t.schedule(new TimerTask() {
//TODO add delays and error
@Override
public void run() {
//figure out timing
long now = new Date().getTime();
long dtMili = now - lastUpdateTime;
lastUpdateTime = now;
double dt = dtMili / 1000.0;
// double dth = desiredWheelTh - wheelTh;
// if(dth > .1){
// dth = .1;
// }else if(dth < -.1){
// dth = -.1;
// }
wheelTh = desiredWheelTh;//wheelTh + dth;
double heading = Util.normalizeAngleDeg(wheelTh + th); //the direction of the front wheel in world frame
double headingRad = Math.toRadians(heading);
//now update the internal state
x = x + dx * Math.cos(headingRad) * dt - dy * Math.sin(headingRad) * dt + 0;//(2*Math.random()-1)/10;
y = y + dx * Math.sin(headingRad) * dt + dy * Math.cos(headingRad) * dt + 0;//(2*Math.random()-1)/10;
th = heading;
//TODO make pose message periodic
simPosePub.publish(new GPSPoseMessage(new Date(), y, x, th));
}
}, 1000, 25);
}
/**
* Getter for the wheel angle
*
* @return the current wheel value
*/
public double getWheelTh() {
return wheelTh;
}
/**
* updates the orientation of the front wheel
*
* @param newWheelTh the orientation of the front wheel
*/
public void setWheelTh(double newWheelTh) {
desiredWheelTh = newWheelTh;
}
/**
* @return the x
*/
public double getX() {
return x;
}
/**
* @param x the x to set
*/
public void setX(double x) {
this.x = x;
}
/**
* @return the y
*/
public double getY() {
return y;
}
/**
* @param y the y to set
*/
public void setY(double y) {
this.y = y;
}
/**
* @return the current th value in degrees
*/
public double getTh() {
return th;
}
/**
* @param th the th to set in degrees
*/
public void setTh(double th) {
this.th = th;
}
/**
* @return the dx
*/
public double getDx() {
return dx;
}
/**
* @param dx the dx to set
*/
public void setDx(double dx) {
this.dx = dx;
}
/**
* @return the dy
*/
public double getDy() {
return dy;
}
/**
* @param dy the dy to set
*/
public void setDy(double dy) {
this.dy = dy;
}
}