package com.roboclub.robobuggy.nodes.planners; import com.roboclub.robobuggy.main.Util; import com.roboclub.robobuggy.messages.GPSPoseMessage; import com.roboclub.robobuggy.messages.GpsMeasurement; import com.roboclub.robobuggy.nodes.localizers.LocalizerUtil; import com.roboclub.robobuggy.ros.NodeChannel; import java.util.ArrayList; import java.util.Date; /** * Plans a path based on a set of waypoints */ public class WayPointFollowerPlanner extends PathPlannerNode { private ArrayList<GpsMeasurement> wayPoints; private GPSPoseMessage pose; //TODO change this to a reasonable type /** * @param wayPoints the list of waypoints to follow */ public WayPointFollowerPlanner(ArrayList<GpsMeasurement> wayPoints) { super(NodeChannel.PATH_PLANNER); this.wayPoints = wayPoints; pose = new GPSPoseMessage(new Date(0), 0, 0, 0);// temp measurment } @Override public void updatePositionEstimate(GPSPoseMessage m) { pose = m; } //find the closest way point //TODO turn into a binary search private static int getClosestIndex(ArrayList<GpsMeasurement> wayPoints, GPSPoseMessage currentLocation) { double min = Double.MAX_VALUE; //note that the brakes will definitely deploy at this int closestIndex = -1; for (int i = 0; i < wayPoints.size(); i++) { double d = GPSPoseMessage.getDistance(currentLocation, wayPoints.get(i).toGpsPoseMessage(0)); if (d < min) { min = d; closestIndex = i; } } return closestIndex; } @Override public double getCommandedSteeringAngle() { int closestIndex = getClosestIndex(wayPoints, pose); if (closestIndex == -1) { return 17433504; //A dummy value that we can never get } double delta = 10; //meters //pick the first point that is at least delta away //pick the point to follow int targetIndex = closestIndex; while (targetIndex < wayPoints.size() && GPSPoseMessage.getDistance(pose, wayPoints.get(targetIndex).toGpsPoseMessage(0)) < delta) { targetIndex = targetIndex + 1; } //if we are out of points then just go straight if (targetIndex >= wayPoints.size()) { return 0; } GpsMeasurement targetPoint = wayPoints.get(targetIndex); //find a path from our current location to that point double dLon = targetPoint.getLongitude() - pose.getLongitude(); double dLat = targetPoint.getLatitude() - pose.getLatitude(); double desiredHeading = Math.toDegrees(Math.atan2(LocalizerUtil.convertLatToMeters(dLat), LocalizerUtil.convertLonToMeters(dLon))); // basically we want all of our angles to be in the same range, so that we don't // have weird wraparound desiredHeading = Util.normalizeAngleDeg(desiredHeading); double poseHeading = Util.normalizeAngleDeg(pose.getHeading()); //find the angle we need to reach that point return Util.normalizeAngleDeg(desiredHeading - poseHeading); } @Override protected boolean getDeployBrakeValue() { return false; /* int closestIndex = getClosestIndex(wayPoints,pose); if(closestIndex == -1){ return true; } // if closest point is too far away throw breaks boolean shouldBrake = GPSPoseMessage.getDistance(pose, wayPoints.get(closestIndex).toGpsPoseMessage(0)) >= 5.0; return shouldBrake; */ } }