Expand Up @@ -3,13 +3,18 @@ import ev3dev.hardware.EV3DevMotorDevice; import ev3dev.hardware.EV3DevPlatforms; import ev3dev.sensors.Battery; import ev3dev.utils.DataChannelRereader; import ev3dev.utils.DataChannelRewriter; import lejos.hardware.port.Port; import lejos.robotics.RegulatedMotor; import lejos.robotics.RegulatedMotorListener; import lejos.utility.Delay; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Closeable; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; Expand All @@ -18,12 +23,12 @@ * Abstraction for a Regulated motors motors. * The basic control methods are: * <code>forward, backward, reverseDirection, stop</code> * and <code>flt</code>. To set eachmotors 's velocity, use {@link #setSpeed(int) * and <code>flt</code>. To set eachmotor 's velocity, use {@link #setSpeed(int) * <code>setSpeed </code> }. * The maximum velocity of the motors is limited by the battery voltage and load. * With no load, the maximum degrees per second is about 100 times the voltage * (for the large EV3 motors). <br> * The velocity is regulated by comparing thetacho count with velocity times elapsed * The velocity is regulated by comparing thetachometer count with velocity times elapsed * time, and adjusting motors power to keep these closely matched. Changes in velocity * will be made at the rate specified via the * <code> setAcceleration(int acceleration)</code> method. Expand All @@ -42,21 +47,35 @@ * @author Roger Glassey * @author Andy Shaw * @author Juan Antonio Breña Moral * @author David Walend */ public abstract class BaseRegulatedMotor extends EV3DevMotorDevice implements RegulatedMotor { public abstract class BaseRegulatedMotor extends EV3DevMotorDevice implements RegulatedMotor, Closeable { private static final Logger log = LoggerFactory.getLogger(BaseRegulatedMotor.class); // Following should be set to the max SPEED (in deg/sec) of the motor when free running and powered by 9V protected final int MAX_SPEED_AT_9V; private int speed = 360; //todo never used protected int acceleration = 6000; private boolean regulationFlag = true; private final List<RegulatedMotorListener> listenerList; private final DataChannelRereader odometerRereader; private final DataChannelRereader stateRereader; private final DataChannelRereader dutyCycleRereader; private final DataChannelRereader speedRereader; private final DataChannelRewriter commandRewriter; private final DataChannelRewriter stopCommandRewriter; private final DataChannelRewriter dutyCycleRewriter; private final DataChannelRewriter speedRewriter; private final DataChannelRewriter positionRewriter; /** * Constructor * Expand Down Expand Up @@ -96,12 +115,38 @@ public BaseRegulatedMotor(final Port motorPort, float moveP, float moveI, float this.detect(TACHO_MOTOR, port); //TODO Review to implement asynchronous solution Delay.msDelay(1000); this.setStringAttribute(COMMAND, RESET); odometerRereader = new DataChannelRereader(Path.of(PATH_DEVICE.toString(),POSITION),8); stateRereader = new DataChannelRereader(Path.of(PATH_DEVICE.toString(),STATE),32); dutyCycleRereader = new DataChannelRereader(Path.of(PATH_DEVICE.toString(),DUTY_CYCLE),32); speedRereader = new DataChannelRereader(Path.of(PATH_DEVICE.toString(),SPEED),32); commandRewriter = new DataChannelRewriter(Path.of(PATH_DEVICE.toString(),COMMAND),32); stopCommandRewriter = new DataChannelRewriter(Path.of(PATH_DEVICE.toString(),STOP_COMMAND),32); dutyCycleRewriter = new DataChannelRewriter(Path.of(PATH_DEVICE.toString(),DUTY_CYCLE),32); speedRewriter = new DataChannelRewriter(Path.of(PATH_DEVICE.toString(),SPEED),32); positionRewriter = new DataChannelRewriter(Path.of(PATH_DEVICE.toString(),POSITION_SP),32); commandRewriter.writeString(RESET); if (log.isDebugEnabled()) { log.debug("Motor ready to use on Port: {}", motorPort.getName()); } } @Override public void close() throws IOException { odometerRereader.close(); stateRereader.close(); dutyCycleRereader.close(); speedRereader.close(); commandRewriter.close(); stopCommandRewriter.close(); dutyCycleRewriter.close(); speedRewriter.close(); positionRewriter.close(); } /** * Removes this motors from the motors regulation system. After this call * the motors will be in float mode and will have stopped. Note calling any Expand All @@ -117,10 +162,10 @@ public boolean suspendRegulation() { /** * @return the current tachometer count. * @seelejos.robotics. RegulatedMotor#getTachoCount() * @see RegulatedMotor#getTachoCount() */ public int getTachoCount() { returngetIntegerAttribute(POSITION ); returnodometerRereader.readAsciiInt( ); } /** Expand All @@ -141,9 +186,9 @@ public float getPosition() { public void forward() { this.setSpeedDirect(this.speed); if (!this.regulationFlag) { this.setStringAttribute(COMMAND, RUN_DIRECT);commandRewriter.writeString( RUN_DIRECT); } else { this.setStringAttribute(COMMAND, RUN_FOREVER);commandRewriter.writeString( RUN_FOREVER); } for (RegulatedMotorListener listener : listenerList) { Expand All @@ -155,9 +200,9 @@ public void forward() { public void backward() { this.setSpeedDirect(-this.speed); if (!this.regulationFlag) { this.setStringAttribute(COMMAND, RUN_DIRECT);commandRewriter.writeString( RUN_DIRECT); } else { this.setStringAttribute(COMMAND, RUN_FOREVER);commandRewriter.writeString( RUN_FOREVER); } for (RegulatedMotorListener listener : listenerList) { Expand Down Expand Up @@ -227,8 +272,8 @@ public void stop(boolean immediateReturn) { * @param immediateReturn Whether the function should busy-wait until the motor stops reporting the 'running' state. */ private void doStop(String mode, boolean immediateReturn) { this.setStringAttribute(STOP_COMMAND, mode);this.setStringAttribute(COMMAND, STOP);stopCommandRewriter.writeString( mode);commandRewriter.writeString( STOP); if (!immediateReturn) { waitComplete(); Expand All @@ -252,7 +297,7 @@ private void doStop(String mode, boolean immediateReturn) { */ @Override public boolean isMoving() { return(this.getStringAttribute(STATE ).contains(STATE_RUNNING) ); returnstateRereader.readString( ).contains(STATE_RUNNING); } /** Expand All @@ -269,9 +314,9 @@ public void setSpeed(int speed) { private void setSpeedDirect(int speed) { if (!this.regulationFlag) { this.setIntegerAttribute(DUTY_CYCLE, speed);dutyCycleRewriter.writeAsciiInt( speed); } else { this.setIntegerAttribute(SPEED, speed);speedRewriter.writeAsciiInt( speed); } } Expand All @@ -280,7 +325,7 @@ private void setSpeedDirect(int speed) { * will cause any current move operation to be halted. */ public void resetTachoCount() { this.setStringAttribute(COMMAND, RESET);commandRewriter.writeString( RESET); this.regulationFlag = true; } Expand All @@ -293,16 +338,16 @@ public void resetTachoCount() { */ public void rotate(int angle, boolean immediateReturn) { this.setSpeedDirect(this.speed); this.setIntegerAttribute(POSITION_SP, angle);this.setStringAttribute(COMMAND, RUN_TO_REL_POS);positionRewriter.writeAsciiInt( angle);commandRewriter.writeString( RUN_TO_REL_POS); if (!immediateReturn) { while (this.isMoving()) { // do stuff or do nothing // possibly sleep for some short interval to not block } } //todo this should happen before the busy wait for (RegulatedMotorListener listener : listenerList) { listener.rotationStarted(this, this.getTachoCount(), this.isStalled(), System.currentTimeMillis()); } Expand All @@ -325,16 +370,16 @@ public void rotate(int angle) { */ public void rotateTo(int limitAngle, boolean immediateReturn) { this.setSpeedDirect(this.speed); this.setIntegerAttribute(POSITION_SP, limitAngle);this.setStringAttribute(COMMAND, RUN_TO_ABS_POS);positionRewriter.writeAsciiInt( limitAngle);commandRewriter.writeString( RUN_TO_ABS_POS); if (!immediateReturn) { while (this.isMoving()) { // do stuff or do nothing // possibly sleep for some short interval to not block } } //todo this should happen before the busy wait for (RegulatedMotorListener listener : listenerList) { listener.rotationStarted(this, this.getTachoCount(), this.isStalled(), System.currentTimeMillis()); } Expand All @@ -356,9 +401,9 @@ public void rotateTo(int limitAngle) { */ public int getSpeed() { if (!this.regulationFlag) { returnthis.getIntegerAttribute(DUTY_CYCLE ); returndutyCycleRereader.readAsciiInt( ); } else { returnthis.getIntegerAttribute(SPEED ); returnspeedRereader.readAsciiInt( ); } } Expand All @@ -369,7 +414,7 @@ public int getSpeed() { * @return true if the motors is stalled, else false */ public boolean isStalled() { return (this.getStringAttribute(STATE ).contains(STATE_STALLED)); return (stateRereader.readString( ).contains(STATE_STALLED)); } /** Expand Down Expand Up @@ -414,13 +459,13 @@ public float getMaxSpeed() { return Battery.getInstance().getVoltage() * MAX_SPEED_AT_9V / 9.0f * 0.9f; } @Override /** * sets the acceleration rate of this motor in degrees/sec/sec <br> * The default value is 6000; Smaller values will make speeding up. or stopping * at the end of a rotate() task, smoother; * @param acceleration * @param acceleration acceleration rate of this motor in degrees/sec/sec */ @Override public void setAcceleration(int acceleration) { this.acceleration = Math.abs(acceleration); Expand Down