package com.roboclub.robobuggy.map;
import Jama.Matrix;
import com.roboclub.robobuggy.main.Util;
/**
* @author Trevor Decker
* Representation of a so2 point (x,y,orientation)
*/
public class So2Pose {
private Point location;
private double orientation; //in radians
/**
* @param newLocation the new location
* @param newOrientation the new orientation
*/
public So2Pose(Point newLocation, double newOrientation) {
this.location = newLocation;
this.orientation = Util.normalizeAngleRad(newOrientation);
}
/**
* @param x x cord of the point
* @param y y cord of the point
* @param newOrientation the new orientation
*/
public So2Pose(double x, double y, double newOrientation) {
location = new Point(x, y);
orientation = Util.normalizeAngleRad(newOrientation);
}
/**
* @param postPose the pose that is being applied to the right of the expression
* @return the new So2Pose TODO
*/
public So2Pose mult(So2Pose postPose) {
double[][] aM = { { Math.cos(orientation), -Math.sin(orientation), getX() },
{ Math.sin(orientation), Math.cos(orientation), getY() },
{ 0, 0, 1 } };
double[][] bM = { { Math.cos(postPose.orientation), -Math.sin(postPose.orientation), postPose.getX() },
{ Math.sin(postPose.orientation), Math.cos(postPose.orientation), postPose.getY() },
{ 0, 0, 1 } };
Matrix a = new Matrix(aM);
Matrix b = new Matrix(bM);
Matrix c = a.times(b);
double th = Util.normalizeAngleRad(Math.atan2(c.get(1, 0), c.get(0, 0)));
return new So2Pose(c.get(0, 2), c.get(1, 2), th);
}
/**
* evaluates to the inverse of the so2 pose (the position change needed to get to zero)
*
* @return an So2Pose object that is the inverse of the current object
*/
public So2Pose inverse() {
double[][] mArray = { { Math.cos(orientation), -Math.sin(orientation), getX() },
{ Math.sin(orientation), Math.cos(orientation), getY() },
{ 0, 0, 1 } };
Matrix mMatrix = new Matrix(mArray);
Matrix mMatrixInv = mMatrix.inverse();
double th = Util.normalizeAngleRad(Math.atan2(mMatrixInv.get(1, 0), mMatrixInv.get(0, 0)));
return new So2Pose(mMatrixInv.get(0, 2), mMatrixInv.get(1, 2), th);
}
/**
* updates the values of the pose
*
* @param newPoint the new se2 point to be set
* @param newOrientation the new orientation
*/
public void updatePoint(Point newPoint, double newOrientation) {
this.orientation = Util.normalizeAngleRad(newOrientation);
this.location = newPoint;
}
/**
* returns the most recent position (se2 point) value
*
* @return se2 Point
*/
public Point getSe2Point() {
return location;
}
/**
* @return the x coordinate of the of the se2 position of the pose
*/
public double getX() {
return location.getX();
}
/**
* @return the y coordinate of the se2 position of the pose
*/
public double getY() {
return location.getY();
}
/**
* @return the orientation of the pose
*/
public double getOrientation() {
return orientation;
}
/**
* Evaluates to the identity object for So2Pose (no position, or orientation change)
*
* @return the Identity So2Pose
*/
public static So2Pose identity() {
return new So2Pose(0.0, 0.0, 0.0);
}
/**
* hashcode function needed for storing the object
*/
@Override
public int hashCode() {
return (int) (getOrientation() * getX() * 1000);
}
/**
* equals function for So2Pose that can be used to check if two poses are the same
*
* @return equality
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof So2Pose)) {
return false;
}
So2Pose otherPose = (So2Pose) o;
if (Math.abs(otherPose.getX() - getX()) > .0001) {
return false;
}
if (Math.abs(otherPose.getY() - getY()) > .0001) {
return false;
}
if (Math.abs(otherPose.getOrientation() - getOrientation()) > .0001) {
return false;
}
//all values were equal so the two poses represent the same pose aka they are equal
return true;
}
/**
* evaluates to a string encoding information about this class
*
* @return a string encoding what this objects information
*/
public String toString() {
return "{So2Pose | x: " + getX() + ", y: " + getY() + ", orintation:" + getOrientation() + "}";
}
}