/* * 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 org.strongback.annotation.ThreadSafe; import org.strongback.command.Requirable; import org.strongback.drive.TankDrive; import org.strongback.util.Values; /** * A motor is a device that can be set to operate at a speed. * * @author Zach Anderson * */ @ThreadSafe public interface Motor extends SpeedSensor, SpeedController, Stoppable, Requirable { public enum Direction { FORWARD, REVERSE, STOPPED } /** * Gets the current speed. * * @return the speed, will be between -1.0 and 1.0 inclusive */ @Override public double getSpeed(); /** * Sets the speed of this {@link Motor}. * * @param speed the new speed as a double, clamped to -1.0 to 1.0 inclusive * @return this object to allow chaining of methods; never null */ @Override public Motor setSpeed(double speed); /** * Stops this {@link Motor}. Same as calling {@code setSpeed(0.0)}. */ @Override default public void stop() { setSpeed(0.0); } /** * Create a new motor that inverts this motor. * * @return the new inverted motor; never null */ default Motor invert() { return Motor.invert(this); } /** * Gets the current {@link Direction} of this {@link Motor}, can be {@code FORWARD}, {@code REVERSE}, or {@code STOPPED}. * * @return the {@link Direction} of this {@link Motor} */ default public Direction getDirection() { int direction = Values.fuzzyCompare(getSpeed(), 0.0); if (direction < 0) return Direction.REVERSE; else if (direction > 0) return Direction.FORWARD; else return Direction.STOPPED; } /** * Create a new {@link Motor} instance that is actually composed of two other motors that will be controlled identically. * This is useful when multiple motors are controlled in the same way, such as on one side of a {@link TankDrive}. * * @param motor1 the first motor, and the motor from which the speed is read; may not be null * @param motor2 the second motor; may not be null * @return the composite motor; never null */ static Motor compose(Motor motor1, Motor motor2) { return new Motor() { @Override public double getSpeed() { return motor1.getSpeed(); } @Override public Motor setSpeed(double speed) { motor1.setSpeed(speed); motor2.setSpeed(speed); return this; } }; } /** * Create a new {@link Motor} instance that is actually composed of three other motors that will be controlled identically. * This is useful when multiple motors are controlled in the same way, such as on one side of a {@link TankDrive}. * * @param motor1 the first motor, and the motor from which the speed is read; may not be null * @param motor2 the second motor; may not be null * @param motor3 the third motor; may not be null * @return the composite motor; never null */ static Motor compose(Motor motor1, Motor motor2, Motor motor3) { return new Motor() { @Override public double getSpeed() { return motor1.getSpeed(); } @Override public Motor setSpeed(double speed) { motor1.setSpeed(speed); motor2.setSpeed(speed); motor3.setSpeed(speed); return this; } }; } /** * Create a new {@link Motor} instance that inverts the speed sent to and read from another motor. This is useful on * {@link TankDrive}, where all motors on one side are physically inverted compared to the motors on the other side. * <p> * For example: * <pre> * Motor left = ... * Motor right = ... * DriveTrain drive = TankDrive.create(left, Motor.invert(right)); * </pre> or <pre> * Motor leftFront = ... * Motor leftRear = ... * Motor rightFront = ... * Motor rightRear = ... * Motor left = Motor.compose(leftFront,leftRear); * Motor right = Motor.compose(rightFront,rightRear); * DriveTrain drive = TankDrive.create(left, Motor.invert(right)); * </pre> * * @param motor the motor to invert; may not be null * @return the inverted motor; never null */ static Motor invert(Motor motor) { return new Motor() { @Override public Motor setSpeed(double speed) { motor.setSpeed(-1 * speed); return this; } @Override public double getSpeed() { return -1 * motor.getSpeed(); } }; } }