/*
* Strongback
* Copyright 2015, Strongback and individual contributors by the @authors tag.
* See the COPYRIGHT.txt in the distribution for a full listing of individual
* contributors.
*
* Licensed under the MIT License; you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.strongback.components;
import java.util.function.DoubleSupplier;
import org.strongback.annotation.ThreadSafe;
/**
* A sensor that returns an angle. The sensor's can be {@link #zero() zeroed} to reset the angle at which the sensor considers 0
* degrees.
*/
@ThreadSafe
@FunctionalInterface
public interface AngleSensor extends Zeroable {
/**
* Gets the angular displacement in continuous degrees.
*
* @return the positive or negative angular displacement
*/
public double getAngle();
/**
* Change the output so that the current angle is considered to be 0.
*
* @return this object to allow chaining of methods; never null
*/
@Override
default public AngleSensor zero() {
return this;
}
/**
* Compute the change in angle between the {@link #getAngle() current angle} and the target angle, using the given tolerance
* for the difference. The result is the angle that this sensor must rotate to reach the target angle, and may be positive
* or negative
*
* @param targetAngle the target angle
* @param tolerance the allowed tolerance in degrees between the two angles
* @return the positive or negative angular displacement required for this sensor to reach the target angle, or 0.0d if the
* two angles are already within the specified {@code tolerance}
*/
default public double computeAngleChangeTo(double targetAngle, double tolerance) {
double diff = targetAngle - this.getAngle();
return Math.abs(diff) <= Math.abs(tolerance) ? 0.0 : diff;
}
/**
* Create an angle sensor around the given function that returns the angle.
*
* @param angleSupplier the function that returns the angle; may not be null
* @return the angle sensor
*/
public static AngleSensor create(DoubleSupplier angleSupplier) {
return new AngleSensor() {
private volatile double zero = 0;
@Override
public double getAngle() {
return angleSupplier.getAsDouble() - zero;
}
@Override
public AngleSensor zero() {
zero = angleSupplier.getAsDouble();
return this;
}
};
}
/**
* Inverts the specified {@link AngleSensor} so that negative angles become positive angles.
*
* @param sensor the {@link AngleSensor} to invert
* @return an {@link AngleSensor} that reads the opposite of the original sensor
*/
public static AngleSensor invert(AngleSensor sensor) {
return new AngleSensor() {
@Override
public double getAngle() {
double angle = sensor.getAngle();
return angle == 0.0 ? 0.0 : -angle;
}
@Override
public AngleSensor zero() {
return sensor.zero();
}
};
}
}