package com.roboclub.robobuggy.nodes.localizers; import com.roboclub.robobuggy.map.So2Pose; import com.roboclub.robobuggy.messages.EncoderMeasurement; import com.roboclub.robobuggy.messages.GPSPoseMessage; 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; import java.util.Date; /** * @author Trevor Decker * <p> * This node produces a position estimate with full trust based only on input from the front wheel * encoder and the front wheel commanded angle */ public class OdomLocalizer extends PeriodicNode { private So2Pose pose; private Publisher posePub = new Publisher(NodeChannel.POSE.getMsgPath()); private double currentEncoderVal = 0; private double previousEncoderVal = 0; private volatile double currentAngle = 0; private double previousAngle = 0; /** * initializes a new odomlocalizer */ public OdomLocalizer() { super(new BuggyBaseNode(NodeChannel.POSE), 100, "odomLocalizer"); // Initialize subscriber to encoder measurements // Since the Encoder sub only consumes currentAngle, by making it volatile we allow // the callbacks to run on different threads/procs and updates will still happen atomically. new Subscriber("OdomLoc", NodeChannel.ENCODER.getMsgPath(), new MessageListener() { @Override public void actionPerformed(String topicName, Message m) { EncoderMeasurement encM = (EncoderMeasurement) m; double dist = encM.getDistance(); previousEncoderVal = currentEncoderVal; currentEncoderVal = dist; if (pose == null) { pose = new So2Pose(0.0, 0.0, 0.0); } double deltaAngle = currentAngle - previousAngle; double deltaEncoder = currentEncoderVal - previousEncoderVal; So2Pose deltaPose = new So2Pose(deltaEncoder, 0.0, deltaAngle); pose = pose.mult(deltaPose); posePub.publish(new GPSPoseMessage(new Date(), pose.getX(), pose.getY(), pose.getOrientation())); previousAngle = currentAngle; } }); //Initialize subscriber for what steering angle low level is currently at new Subscriber("OdomLoc", NodeChannel.STEERING.getMsgPath(), new MessageListener() { @Override public void actionPerformed(String topicName, Message m) { SteeringMeasurement steerMeasur = (SteeringMeasurement) m; currentAngle = (steerMeasur.getAngle()) * Math.PI / 180; } }); } @Override protected void update() { } @Override protected boolean startDecoratorNode() { // TODO Auto-generated method stub return false; } @Override protected boolean shutdownDecoratorNode() { // TODO Auto-generated method stub return false; } }