package com.roboclub.robobuggy.simulation; import com.roboclub.robobuggy.main.Util; import com.roboclub.robobuggy.map.So2Pose; import com.roboclub.robobuggy.messages.BrakeControlMessage; import com.roboclub.robobuggy.messages.DriveControlMessage; import com.roboclub.robobuggy.messages.EncoderMeasurement; import com.roboclub.robobuggy.messages.SteeringMeasurement; import com.roboclub.robobuggy.nodes.baseNodes.BuggyBaseNode; import com.roboclub.robobuggy.nodes.baseNodes.PeriodicNode; import com.roboclub.robobuggy.ros.Message; import com.roboclub.robobuggy.ros.MessageListener; import com.roboclub.robobuggy.ros.NodeChannel; import com.roboclub.robobuggy.ros.Publisher; import com.roboclub.robobuggy.ros.Subscriber; /** * This node listens to commands from topics and produces messages similar to what the RBSM node would do * based on a model of how the buggy behaves * * @author Trevor Decker */ public class SimulatedRBSMNode extends PeriodicNode { //for determining the encoder and commanded angle based on the //transform between the current pose and the last pose private So2Pose lastPose = new So2Pose(0, 0, 0); private double encoderDistance = 0; private Publisher messagePubEnc; private Publisher messagePubControllerSteering; private Publisher messagePubBrakeState; private Publisher messagePubSteering; private int commandedAngle = 0; private boolean commandedBrakeEngaged = true; /** * The constructor for the simulatedRBSMNode */ public SimulatedRBSMNode() { super(new BuggyBaseNode(NodeChannel.ENCODER), 100, "simulated_rbsm_node"); SimulatedBuggy simBuggy = SimulatedBuggy.getInstance(); // TODO Auto-generated constructor stub messagePubEnc = new Publisher(NodeChannel.ENCODER.getMsgPath()); messagePubControllerSteering = new Publisher(NodeChannel.STEERING_COMMANDED.getMsgPath()); messagePubBrakeState = new Publisher(NodeChannel.BRAKE_STATE.getMsgPath()); messagePubSteering = new Publisher(NodeChannel.STEERING.getMsgPath()); //changes the angle that we are attempting to drive at based on the commanded angle messages we are getting //Initialize subscribers to commanded angle and brakes state new Subscriber("simRbsmNode", NodeChannel.DRIVE_CTRL.getMsgPath(), new MessageListener() { @Override public void actionPerformed(String topicName, Message m) { commandedAngle = ((DriveControlMessage) m).getAngleInt(); } }); new Subscriber("simRbsmNode", NodeChannel.BRAKE_CTRL.getMsgPath(), new MessageListener() { @Override public void actionPerformed(String topicName, Message m) { commandedBrakeEngaged = ((BrakeControlMessage) m).isBrakeEngaged(); simBuggy.setBrakesDown(commandedBrakeEngaged); //echo the brake message messagePubBrakeState.publish(m); } }); resume();//needed to start the node } @Override protected void update() { SimulatedBuggy simBuggy = SimulatedBuggy.getInstance(); if (lastPose == null) { lastPose = new So2Pose(simBuggy.getX(), simBuggy.getY(), simBuggy.getTh()); } //get an updated representation of the buggy current pose So2Pose newPose = new So2Pose(simBuggy.getX(), simBuggy.getY(), simBuggy.getTh()); //find the difference between the last observed pose and this pose // So2Pose dPose = newPose.mult(lastPose.inverse()); TODO look into why this does not work //use that information to fill out messages to be published //the distance between the two is the amount which the encoder would be incremented double dx = newPose.getX() - lastPose.getX();//dPose.getX(); double dy = newPose.getY() - lastPose.getY();//dPose.getY(); double d = Math.sqrt(dx * dx + dy * dy); encoderDistance = encoderDistance + d; lastPose = newPose; messagePubEnc.publish(new EncoderMeasurement(encoderDistance, 0.0)); //TODO calculate the actual velocity double potAngle = Util.normalizeAngleDeg(simBuggy.getWheelTh()); messagePubControllerSteering.publish(new SteeringMeasurement(potAngle)); messagePubSteering.publish(new SteeringMeasurement(potAngle)); int outputAngle = commandedAngle; //update the commanded angle if (outputAngle > 1000) { outputAngle = 1000; } else if (outputAngle < -1000) { outputAngle = -1000; } //TODO set velocity so that the buggy will try and steer towards this angle instead of jumping directly to it simBuggy.setWheelTh((double) outputAngle / 1000.0); } @Override protected boolean startDecoratorNode() { // TODO Auto-generated method stub return false; } @Override protected boolean shutdownDecoratorNode() { // TODO Auto-generated method stub return false; } }