This is the 2020 repository of the FRC team 972 Ironclaw.
The project board for this repository is located here. Feel free to assign yourself to tasks and to complete them.
Overall the code structure is very basic and may be in some need of revising. Under ~\src\main\java\frc\robot there are two directories, described below. In addion there are two files, robot.java and main.java, which control robot functions at the highest level.
Pretty much everything that controls a specific action that the robot can take, this includes the conventional subsystems.
All of the general purpose classes that are used throughout the robot code.
Do ctrl-shift-p
to open the quick actions bar, then select manage vendor libraries. From there select install new library (online)
and paste the urls below before pressing ok
.
http://www.revrobotics.com/content/sw/max/sdk/REVRobotics.json
https://www.kauailabs.com/dist/frc/2020/navx_frc.json
http://devsite.ctr-electronics.com/maven/release/com/ctre/phoenix/Phoenix-latest.json
https://google.github.io/styleguide/javaguide.html
Unit tests are simple to write and provide many benefits. The steps for making tests are detailed below:
Navigate to FRC2020/src/test/java/frc/robot/
Add a file in the same respective folder as the main class is in main. For example, if one wanted to write a test for the Intake.java class located in ~/main/java/frc/robot/controllers, the test should be written in a file named IntakeTest.java located in ~/test/java/frc/robot/controllers.
Add the following code to the test file:
package frc.robot.util;
import static org.junit.Assert.*;
import org.junit.*;
// Replace YourTest with the name of the test file
public class YourTest {
@Test
// The function should have a descriptive name for what it is testing.
public void exampleTestFunction() {
// Add test code here
// Assert equals compares two values to determine if they are equal, if they are the test is PASSED
assertEquals(expected, actual, delta);
}
}
This test is designed to test the Calculator.java class, which has the methods add(), multuply() and divide().
package frc.robot.util;
import static org.junit.Assert.*;
import org.junit.*;
public class CalculatorTest {
public Calculator calculator = new Calculator();
@Test
// This function tests if the addition feature of Calculator works
public void testAdd() {
int actualSum = calculator.add(10, 5);
assertEquals(10 + 5, actualSum, 1);
}
@Test
// This function tests if the multiplication feature of Calculator works
public void testMultiply() {
int actualProduct = calculator.multiply(3, 7);
assertEquals(3 * 7, actualProduct, 1);
}
@Test
// This function makes sure that 4 / 2 does not equal 73
public void testDivide() {
int actualProduct = calculator.divide(4, 2);
assertNotEquals(73, actualQuotient);
}
}
This test is designed to test the NavX.java class. The test is located here.
package frc.robot.controllers;
import static org.junit.Assert.*;
import org.junit.*;
import static org.mockito.Mockito.*;
import com.kauailabs.navx.frc.AHRS;
public class NavXTest {
@Test
// Tests getting the rawHeading of a mocked AHRS
public void testRawHeading() {
// Makes a mock AHRS, it acts in almost every way like a real AHRS
AHRS mockAhrs = mock(AHRS.class);
// Declares and initializes NavX
NavX navX = new NavX(mockAhrs);
// When the AHRS.getAngle() method is called, it will return 5.0
when(mockAhrs.getAngle()).thenReturn(5.0);
navX.ahrs = mockAhrs;
// Assert
assertEquals(5.0, navX.getRawHeading(), 0.1);
}
@Test
// Tests getting the rawHeading of a mocked AHRS
public void testLimitedHeading() {
// Makes a mock AHRS, it acts in almost every way like a real AHRS
AHRS mockAhrs = mock(AHRS.class);
// Declares and initializes NavX
NavX navX = new NavX(mockAhrs);
// When the getPressure() is called, it will return the float 5.0f
// On the second call, it will return the float 6.5f
when(mockAhrs.getAngle()).thenReturn(258.0);
navX.ahrs = mockAhrs;
// Assert
assertEquals(-102.0, navX.getConstrainedHeading(), 0.1);
}
@Test
// Tests getting the rawHeading of a mocked AHRS
public void testBarometer() {
// Makes a mock AHRS, it acts in almost every way like a real AHRS
AHRS mockAhrs = mock(AHRS.class);
// Declares and initializes NavX
NavX navX = new NavX(mockAhrs);
// When the getPressure() is called, it will return the float 5.0f
// On the second call, it will return the float 6.5f
when(mockAhrs.getBarometricPressure()).thenReturn(3.0f);
navX.ahrs = mockAhrs;
// Assert
assertEquals(3.0f, navX.getBarometricPressure(), 0.1f);
}
}
The example below demonstrates how to read the value used as the input to the spark's .set method. This style of test can be applied to many different classes that use motors.
package frc.robot.controllers;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import org.junit.*;
import com.revrobotics.CANSparkMax;
public class NeoDrivetrainTest
{
// Declaration of variables used to store inputs to motors
public double lm1Power = 0;
public double lm2Power = 0;
public double rm1Power = 0;
public double rm2Power = 0;
// Creation of mock sparks and putting them into NeoDrivetrain
public CANSparkMax lm1 = mock(CANSparkMax.class);
public CANSparkMax lm2 = mock(CANSparkMax.class);
public CANSparkMax rm1 = mock(CANSparkMax.class);
public CANSparkMax rm2 = mock(CANSparkMax.class);
public NeoDrivetrain neoDrivetrain = new NeoDrivetrain(lm1, lm2, rm1, rm2);
// @Before allows for the setup() method to be called before any other methods
@Before
public void setup() {
// Basically replaces the .set() method for mock Spark with
// method that puts input into variable for testing
doAnswer(invocation -> {
Double power = invocation.getArgument(0, Double.class);
lm1Power = power.doubleValue();
return null;
}).when(lm1).set(any(Double.class));
doAnswer(invocation -> {
Double power = invocation.getArgument(0, Double.class);
lm2Power = power.doubleValue();
return null;
}).when(lm2).set(any(Double.class));
doAnswer(invocation -> {
Double power = invocation.getArgument(0, Double.class);
rm1Power = power.doubleValue();
return null;
}).when(rm1).set(any(Double.class));
doAnswer(invocation -> {
Double power = invocation.getArgument(0, Double.class);
rm2Power = power.doubleValue();
return null;
}).when(rm2).set(any(Double.class));
}
// Simple test that calls method that calls in turn the .set function of motors
@Test
public void testTankDrive0() {
neoDrivetrain.tankDrive(1.0, 1.0);
assertEquals(1.0, lm1Power, 0.1);
assertEquals(1.0, lm2Power, 0.1);
assertEquals(1.0, rm1Power, 0.1);
assertEquals(1.0, rm2Power, 0.1);
}
}