Merge changes I7e8735d9,Ida66361c

* changes:
  Adds/Formats the CANJaguar.set() Javadocs
  Adds CANJaguar integration tests testing that in every control mode the motors can be rotated Adds a separate test suite for explicitly testing CAN
This commit is contained in:
Brad Miller (WPI)
2014-06-27 08:46:41 -07:00
committed by Gerrit Code Review
12 changed files with 496 additions and 72 deletions

View File

@@ -245,15 +245,15 @@ public class CANJaguar implements MotorSafety, PIDOutput, SpeedController, LiveW
}
/**
* set the output set-point value.
*
* The scale and the units depend on the mode the Jaguar is in.
* In PercentVbus Mode, the outputValue is from -1.0 to 1.0 (same as PWM Jaguar).
* In Voltage Mode, the outputValue is in Volts.
* In Current Mode, the outputValue is in Amps.
* In Speed Mode, the outputValue is in Rotations/Minute.
* Sets the output set-point value.
*
* The scale and the units depend on the mode the Jaguar is in.<br>
* In PercentVbus Mode, the outputValue is from -1.0 to 1.0 (same as PWMJaguar).<br>
* In Voltage Mode, the outputValue is in Volts. <br>
* In Current Mode, the outputValue is in Amps. In Speed Mode, the outputValue is in
* Rotations/Minute.<br>
* In Position Mode, the outputValue is in Rotations.
*
*
* @param outputValue The set-point to sent to the motor controller.
* @param syncGroup The update group to add this set() to, pending UpdateSyncGroup(). If 0, update immediately.
*/
@@ -306,6 +306,19 @@ public class CANJaguar implements MotorSafety, PIDOutput, SpeedController, LiveW
verify();
}
/**
* Sets the output set-point value.
*
* The scale and the units depend on the mode the Jaguar is in.<br>
* In PercentVbus Mode, the outputValue is from -1.0 to 1.0 (same as PWMJaguar).<br>
* In Voltage Mode, the outputValue is in Volts. <br>
* In Current Mode, the outputValue is in Amps. In Speed Mode, the outputValue is in
* Rotations/Minute.<br>
* In Position Mode, the outputValue is in Rotations.
*
* @param value
* The set-point to sent to the motor controller.
*/
public void set(double value) {
set(value, (byte)0);
}

View File

@@ -18,23 +18,21 @@ import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import edu.wpi.first.wpilibj.can.ICANData;
import edu.wpi.first.wpilibj.can.AbstractCANTest;
import edu.wpi.first.wpilibj.command.AbstractCommandTest;
import edu.wpi.first.wpilibj.fixtures.CANMotorEncoderFixture;
import edu.wpi.first.wpilibj.fixtures.MotorEncoderFixture;
import edu.wpi.first.wpilibj.test.AbstractComsSetup;
import edu.wpi.first.wpilibj.test.TestBench;
/**
* @author jonathanleitschuh
*
*/
public class CANJaguarTest extends AbstractCommandTest {
public class CANJaguarTest extends AbstractComsSetup implements ICANData{
private static final Logger logger = Logger.getLogger(CANJaguarTest.class.getName());
private CANMotorEncoderFixture me;
private static final double kPotentiometerSettlingTime = 0.05;
private static final double kMotorTime = 0.5;
private static final double kEncoderSettlingTime = 0.25;
private static final double kEncoderPositionTolerance = 5.0/360.0; // +/-5 degrees
private static final double kPotentiometerPositionTolerance = 10.0/360.0; // +/-10 degrees
@Override
protected Logger getClassLogger() {
@@ -110,49 +108,6 @@ public class CANJaguarTest extends AbstractCommandTest {
assertEquals(0, me.getMotor().getFaults());
}
@Test
public void testPercentForwards() {
me.getMotor().setPercentMode(CANJaguar.kQuadEncoder, 360);
me.getMotor().enableControl();
me.getMotor().set(0.0f);
/* The motor might still have momentum from the previous test. */
Timer.delay(kEncoderSettlingTime);
double initialPosition = me.getMotor().getPosition();
/* Drive the speed controller briefly to move the encoder */
me.getMotor().set(1.0f);
Timer.delay(kMotorTime);
me.getMotor().set(0.0f);
/* The position should have increased */
assertThat("CAN Jaguar position should have increased after the motor moved", me.getMotor().getPosition(), is(greaterThan(initialPosition)));
}
/**
* Test if we can drive the motor backwards in percentage mode and get a
* position back
*/
@Test
public void testPercentReverse() {
me.getMotor().setPercentMode(CANJaguar.kQuadEncoder, 360);
me.getMotor().enableControl();
me.getMotor().set(0.0f);
/* The motor might still have momentum from the previous test. */
Timer.delay(kEncoderSettlingTime);
double initialPosition = me.getMotor().getPosition();
/* Drive the speed controller briefly to move the encoder */
me.getMotor().set(-1.0f);
Timer.delay(kMotorTime);
me.getMotor().set(0.0f);
/* The position should have decreased */
assertThat( "CAN Jaguar position should have decreased after the motor moved", me.getMotor().getPosition(), is(lessThan(initialPosition)));
}
/**
* Test if we can set a position and reach that position with PID control on
@@ -279,4 +234,5 @@ public class CANJaguarTest extends AbstractCommandTest {
/* The position should have increased */
assertThat("CAN Jaguar should have moved forwards while the reverse limit was on", me.getMotor().getPosition(), is(greaterThan(initialPosition)));
}
}

View File

@@ -0,0 +1,78 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.can;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertThat;
import org.junit.After;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.fixtures.CANMotorEncoderFixture;
import edu.wpi.first.wpilibj.test.AbstractComsSetup;
/**
* @author jonathanleitschuh
*
*/
public abstract class AbstractCANTest extends AbstractComsSetup implements ICANData{
protected CANMotorEncoderFixture me;
/**
* Tests that CAN in a certain mode will rotate forwards. The implementation of this method is left up to the extending class because each will require difrent values.
* Should call {@link AbstractCANTest#testRotateForward(double, double)}
*/
abstract public void testRotateForward();
/**
* Tests that CAN in a certain mode will rotate forwards. The implementation of this method is left up to the extending class because each will require difrent values.
* Should call {@link AbstractCANTest#testRotateReverse(double, double)}
*/
abstract public void testRotateReverse();
@After
public final void tearDown() throws Exception {
me.teardown();
}
/**
* Tests that a CANMotorEncoderFixture can rotate forward.
* Called by extending TestClasses
* @param stoppedValue the value where the motor will not be spinning in the current mode
* @param runningValue the value where the motor will be spinning in the current mode
*/
protected void testRotateForward(double stoppedValue, double runningValue){
double initialPosition = me.getMotor().getPosition();
/* Drive the speed controller briefly to move the encoder */
me.getMotor().set(runningValue);
Timer.delay(kMotorTime);
me.getMotor().set(stoppedValue);
/* The position should have increased */
assertThat("CAN Jaguar position should have increased after the motor moved", me.getMotor().getPosition(), is(greaterThan(initialPosition)));
}
/**
* Tests that a CANMotorEncoderFixture can rotate in reverse.
* Called by extending TestClasses
* @param stoppedValue the value where the motor will not be spinning in the current mode
* @param runningValue the value where the motor will be spinning in the current mode
*/
protected void testRotateReverse(double stoppedValue, double runningValue){
double initialPosition = me.getMotor().getPosition();
/* Drive the speed controller briefly to move the encoder */
me.getMotor().set(runningValue);
Timer.delay(kMotorTime);
me.getMotor().set(stoppedValue);
/* The position should have decreased */
assertThat( "CAN Jaguar position should have decreased after the motor moved", me.getMotor().getPosition(), is(lessThan(initialPosition)));
}
}

View File

@@ -0,0 +1,26 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.can;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
/**
* @author jonathanleitschuh
*
*/
@RunWith(Suite.class)
@SuiteClasses({ CurrentQuadEncoderModeTest.class,
PercentQuadEncoderModeTest.class,
PositionQuadEncoderModeTest.class,
SpeedQuadEncoderModeTest.class,
VoltageQuadEncoderModeTest.class
})
public class CANTestSuite {
}

View File

@@ -0,0 +1,56 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.can;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import edu.wpi.first.wpilibj.CANJaguar;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.test.TestBench;
/**
* @author jonathanleitschuh
*
*/
public class CurrentQuadEncoderModeTest extends AbstractCANTest {
private static Logger logger = Logger.getLogger(CurrentQuadEncoderModeTest.class.getName());
@Override
protected Logger getClassLogger() {
return logger;
}
@Before
public void setUp() throws Exception {
me = TestBench.getInstance().getCanJaguarPair();
me.setup();
me.getMotor().setCurrentMode(CANJaguar.kQuadEncoder, 360, 5.0, 0.1, 2.0);
me.getMotor().enableControl();
me.getMotor().set(0.0f);
/* The motor might still have momentum from the previous test. */
Timer.delay(kEncoderSettlingTime);
}
@Test
@Override
public void testRotateForward() {
testRotateForward(0, 1.5);
}
@Test
@Override
public void testRotateReverse() {
testRotateReverse(0, -1.5);
}
}

View File

@@ -0,0 +1,19 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.can;
/**
* @author jonathanleitschuh
*
*/
public interface ICANData {
static final double kPotentiometerSettlingTime = 0.05;
static final double kMotorTime = 0.5;
static final double kEncoderSettlingTime = 0.25;
static final double kEncoderPositionTolerance = 5.0/360.0; // +/-5 degrees
static final double kPotentiometerPositionTolerance = 10.0/360.0; // +/-10 degrees
}

View File

@@ -0,0 +1,69 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.can;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import edu.wpi.first.wpilibj.CANJaguar;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.fixtures.CANMotorEncoderFixture;
import edu.wpi.first.wpilibj.test.AbstractComsSetup;
import edu.wpi.first.wpilibj.test.TestBench;
import edu.wpi.first.wpilibj.test.TestBench.BaseCANMotorEncoderFixture;
/**
* @author jonathanleitschuh
*
*/
public class PercentQuadEncoderModeTest extends AbstractCANTest implements ICANData{
private static final Logger logger = Logger.getLogger(PercentQuadEncoderModeTest.class.getName());
@Override
protected Logger getClassLogger() {
return logger;
}
@Before
public void setUp() {
me = TestBench.getInstance().getCanJaguarPair();
me.setup();
me.getMotor().setPercentMode(CANJaguar.kQuadEncoder, 360);
me.getMotor().enableControl();
me.getMotor().set(0.0f);
/* The motor might still have momentum from the previous test. */
Timer.delay(kEncoderSettlingTime);
}
/**
* Test if we can drive the motor forwards in percentage mode and get a
* position back
*/
@Test
@Override
public void testRotateForward() {
testRotateForward(0, 1);
}
/**
* Test if we can drive the motor backwards in percentage mode and get a
* position back
*/
@Test
@Override
public void testRotateReverse() {
testRotateReverse(0, -1);
}
}

View File

@@ -0,0 +1,58 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.can;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import edu.wpi.first.wpilibj.CANJaguar;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.test.TestBench;
/**
* @author jonathanleitschuh
*
*/
public class PositionQuadEncoderModeTest extends AbstractCANTest {
private static final Logger logger = Logger.getLogger(PositionQuadEncoderModeTest.class.getName());
@Override
protected Logger getClassLogger() {
return logger;
}
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
me = TestBench.getInstance().getCanJaguarPair();
me.setup();
me.getMotor().setPositionMode(CANJaguar.kQuadEncoder, 360, 5.0, 0.1, 2.0);
me.getMotor().enableControl();
/* The motor might still have momentum from the previous test. */
Timer.delay(kEncoderSettlingTime);
}
@Test
@Override
public void testRotateForward() {
double initial = me.getMotor().getPosition();
testRotateForward(initial, initial + 50);
}
@Test
@Override
public void testRotateReverse() {
double initial = me.getMotor().getPosition();
testRotateReverse(initial, initial - 50);
}
}

View File

@@ -0,0 +1,70 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.can;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import edu.wpi.first.wpilibj.CANJaguar;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.fixtures.CANMotorEncoderFixture;
import edu.wpi.first.wpilibj.test.AbstractComsSetup;
import edu.wpi.first.wpilibj.test.TestBench;
/**
* @author jonathanleitschuh
*
*/
public class SpeedQuadEncoderModeTest extends AbstractCANTest implements ICANData {
private static final Logger logger = Logger.getLogger(PercentQuadEncoderModeTest.class.getName());
@Override
protected Logger getClassLogger() {
return logger;
}
@Before
public void setUp() throws Exception {
me = TestBench.getInstance().getCanJaguarPair();
me.setup();
me.getMotor().setSpeedMode(CANJaguar.kQuadEncoder, 360, 5.0, 0.1, 2.0);
me.getMotor().enableControl();
me.getMotor().set(0.0f);
/* The motor might still have momentum from the previous test. */
Timer.delay(kEncoderSettlingTime);
}
/**
* Test if we can drive the motor forward in Speed mode and get a
* position back
*/
@Test
public void testRotateForward() {
//Speed is rev/min
testRotateForward(0, 1000);
}
/**
* Test if we can drive the motor backwards in Speed mode and get a
* position back
*/
@Test
public void testRotateReverse() {
//Speed is rev/min
testRotateReverse(0, -1000);
}
}

View File

@@ -0,0 +1,60 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.can;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import edu.wpi.first.wpilibj.CANJaguar;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.fixtures.CANMotorEncoderFixture;
import edu.wpi.first.wpilibj.test.AbstractComsSetup;
import edu.wpi.first.wpilibj.test.TestBench;
/**
* @author jonathanleitschuh
*
*/
public class VoltageQuadEncoderModeTest extends AbstractCANTest implements ICANData {
private static final Logger logger = Logger.getLogger(VoltageQuadEncoderModeTest.class.getName());
@Override
protected Logger getClassLogger() {
return logger;
}
@Before
public void setUp() throws Exception {
me = TestBench.getInstance().getCanJaguarPair();
me.setup();
me.getMotor().setPercentMode(CANJaguar.kQuadEncoder, 360);
me.getMotor().enableControl();
me.getMotor().set(0.0f);
/* The motor might still have momentum from the previous test. */
Timer.delay(kEncoderSettlingTime);
}
@Test
@Override
public void testRotateForward() {
testRotateForward(0, 14);
}
@Test
@Override
public void testRotateReverse() {
testRotateReverse(0, -14);
}
}

View File

@@ -34,9 +34,6 @@ public abstract class MotorEncoderFixture <T extends SpeedController> implements
/**
* Default constructor for a MotorEncoderFixture
* @param motor The SpeedControler for this MotorEncoder pair
* @param aSource One of the inputs for the encoder
* @param bSource The other input for the encoder
*/
public MotorEncoderFixture(){
}
@@ -155,27 +152,47 @@ public abstract class MotorEncoderFixture <T extends SpeedController> implements
/**
* Safely tears down the MotorEncoder Fixture in a way that makes sure that even if an object fails
* to initialize the reset of the fixture can still be torn down and the resources deallocated
*/
@Override
public boolean teardown() {
String type = getType();
if(!tornDown){
boolean wasNull = false;
initialize();
reset();
if(motor instanceof PWM){
if(motor instanceof PWM && motor != null){
((PWM) motor).free();
motor = null;
}
encoder.free();
counters[0].free();
counters[0] = null;
counters[1].free();
counters[1] = null;
aSource.free();
aSource = null;
bSource.free();
bSource = null;
} else if(motor == null) wasNull = true;
if(encoder != null){
encoder.free();
encoder = null;
} else wasNull = true;
if(counters[0] != null){
counters[0].free();
counters[0] = null;
} else wasNull = true;
if(counters[1] != null){
counters[1].free();
counters[1] = null;
} else wasNull = true;
if(aSource != null){
aSource.free();
aSource = null;
} else wasNull = true;
if(bSource != null){
bSource.free();
bSource = null;
} else wasNull = true;
tornDown = true;
if(wasNull){
throw new NullPointerException("MotorEncoderFixture had null params at teardown");
}
} else {
throw new RuntimeException(type + " Motor Encoder torn down multiple times");
}

View File

@@ -29,6 +29,7 @@ import edu.wpi.first.wpilibj.SampleTest;
import edu.wpi.first.wpilibj.TiltPanCameraTest;
import edu.wpi.first.wpilibj.TimerTest;
import edu.wpi.first.wpilibj.WpiLibJTestSuite;
import edu.wpi.first.wpilibj.can.CANTestSuite;
import edu.wpi.first.wpilibj.command.ButtonTest;
import edu.wpi.first.wpilibj.command.CommandParallelGroupTest;
import edu.wpi.first.wpilibj.command.CommandScheduleTest;
@@ -49,6 +50,7 @@ import edu.wpi.first.wpilibj.smartdashboard.SmartDashboardTestSuite;
@RunWith(Suite.class)
@SuiteClasses({
WpiLibJTestSuite.class,
CANTestSuite.class,
CommandTestSuite.class,
SmartDashboardTestSuite.class
})